2016-10-02 135 views
0

我正在構建一個由一個GridView與從一個API提取的圖像組成的用戶界面,我使用的ImageListAdapter和一個MovieFragment,當我啓動應用程序,我只是得到一個空的屏幕。 我試過用preownownloaded的圖像列表,它的工作原理。 從API獲取數據在AsyncTask上,我認爲問題在於時機,gridview.setAdapter()過早調用這一事實。 這是代碼:GridView適配器不填充?沒有按時填充?沒有在onPostExecute()中更新?

public class MainActivity extends AppCompatActivity { 

private final String LOG_TAG = MainActivity.class.getSimpleName(); 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    if (savedInstanceState == null) { 
     getFragmentManager() 
       .beginTransaction() 
       .add(R.id.container, new MovieFragment()) 
       .commit(); 
    } 
}} 

公共類MovieFragment延伸片段{

private final String LOG_TAG = MovieFragment.class.getSimpleName(); 
public ImageListAdapter imageAdapter; 
String urlPopular = "https://api.themoviedb.org/3/movie/popular?api_key="; 
String urlRatings = "https://api.themoviedb.org/3/movie/top_rated?api_key="; 

public MovieFragment() { 
}; 


@Override 
public void onStart() { 
    super.onStart(); 
    FetchMovieData movieTask = new FetchMovieData(); 
    movieTask.execute(urlPopular); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 

    View rootView = inflater.inflate(R.layout.movie_fragment_main, container, false); 
    GridView gridview = (GridView) rootView.findViewById(R.id.grid_view); 
    Log.d(LOG_TAG, imageAdapter.getCount() +""); 
    gridview.setAdapter(imageAdapter); 

    gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     public void onItemClick(AdapterView<?> parent, View v, 
           int position, long id) { 
      Toast.makeText(getActivity(), "" + position, 
        Toast.LENGTH_SHORT).show(); 
     } 
    }); 


    return rootView; 
} 


public class ImageListAdapter extends ArrayAdapter { 
    private Context context; 
    private LayoutInflater inflater; 

    private String[] imageUrls; 

    public ImageListAdapter(Context context, String[] imageUrls) { 
     super(context, R.layout.image_item, imageUrls); 

     this.context = context; 
     this.imageUrls = imageUrls; 
     inflater = LayoutInflater.from(context); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     Log.d(LOG_TAG, imageUrls[position]); 
     if (null == convertView) { 
      convertView = inflater.inflate(R.layout.image_item, parent, false); 
     } 

     Picasso 
       .with(context) 
       .load(imageUrls[position]) 
       .fit() // will explain later 
       .into((ImageView) convertView); 

     return convertView; 
    } 
} 


public class FetchMovieData extends AsyncTask<String,Void,String[][]> { 

    private final String LOG_TAG = FetchMovieData.class.getSimpleName(); 
    @Override 
    protected String[][] doInBackground(String... params) { 
     String url = params[0]; 
     if (params.length == 0){ 
      return null; 
     } 
     // Will contain the raw JSON response as a string. 
     String movieJSON = null; 

     try { 
      movieJSON = getMovieInfo(url); 
     } catch (final IOException e) { 
      Log.d(LOG_TAG, "Error closing stream", e); 
     } 

     try{ 
      return getMovieDataFromJSON(movieJSON); 
     } 
     catch (JSONException e){ 
      Log.d(LOG_TAG, e.getMessage(),e); 
      e.printStackTrace(); 
     } 

     //Just in case... 
     return null; 
    } 
    private String getMovieInfo(String myurl) throws IOException{ 
     HttpURLConnection urlConnection = null; 
     InputStream inputStream = null; 

     try{ 
      URL url = new URL(myurl); 
      urlConnection = (HttpURLConnection) url.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      urlConnection.connect(); 

      inputStream = urlConnection.getInputStream(); 
      StringBuffer stringBuffer = new StringBuffer(); 
      if (inputStream == null){ 
       return null; 
      } 

      BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 

      String line; 
      while ((line = reader.readLine()) != null) { 
       // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) 
       // But it does make debugging a *lot* easier if you print out the completed 
       // buffer for debugging. 
       stringBuffer.append(line + "\n"); 
      } 

      if (stringBuffer.length() == 0) { 
       // Stream was empty. No point in parsing. 
       return null; 
      } 
      Log.d(LOG_TAG, stringBuffer.toString()); 
      return stringBuffer.toString(); 
     } 
     finally { 
      if(urlConnection != null){ 
       urlConnection.disconnect(); 
      } 
     } 
    } 

    private String[][] getMovieDataFromJSON(String jsonObj) throws JSONException{ 

     JSONObject mainJSON = new JSONObject(jsonObj); 

     final String POSTERS = "poster_path"; 
     final String ORIGINAL_TITLE = "original_title"; 
     final String SYNOPSIS = "overview"; 
     final String USER_RATING = "vote_average"; 
     final String RELEASE_DATE = "release_date"; 
     final String RESULTS = "results"; 

     // Building a String[][] of movie info while: 
     // movie[][0] = Poster path 
     // movie[][1] = Original Title 
     // movie[][2] = Synopsis 
     // movie[][3] = User Rating 
     // movie[][4] = Release Date 

     JSONArray movieIndexArray = mainJSON.getJSONArray(RESULTS); 
     String[][] movie = new String[20][5]; 

     for(int i = 0; i < movieIndexArray.length(); i++) { 
      JSONObject movieObject = movieIndexArray.getJSONObject(i); 
      movie[i][0] = movieObject.getString(POSTERS); 
      movie[i][1] = movieObject.getString(ORIGINAL_TITLE); 
      movie[i][2] = movieObject.getString(SYNOPSIS); 
      movie[i][3] = movieObject.getString(USER_RATING); 
      movie[i][4] = movieObject.getString(RELEASE_DATE); 
     } 

     return movie; 
    } 

    private String[] buildPosterArray(String[][] result){ 

     String[] url = new String[20]; 
     Uri.Builder builtUri = new Uri.Builder(); 
     builtUri.scheme("http"); 
     builtUri.authority("image.tmdb.org"); 
     builtUri.appendPath("t"); 
     builtUri.appendPath("p"); 
     builtUri.appendPath("w185"); 

     for (int i = 0 ; i < result.length ; i++){ 
      builtUri.appendEncodedPath((result[i][0])); 
      builtUri.build(); 
      url[i] = builtUri.toString(); 
     } 
     return url; 

    } 
    protected void onPostExecute(String[][] result){ 
     if(result != null){ 
      String[] posterArray = buildPosterArray(result); 
      imageAdapter = new ImageListAdapter(getActivity(), posterArray); 
      Log.d(LOG_TAG, imageAdapter.getCount() +""); 
     } 
    } 


} 

}

回答

0

我終於解決了它,我用BaseAdapter代替ArrayAdapter的延伸:

public class ImageAdapter extends BaseAdapter { 
    private Context mContext; 
    private String[] moviePath; 

    public ImageAdapter(Context c, String[] path) { 

     mContext = c; 
     this.moviePath = path; 
    } 

    public int getCount() { 
     return moviePath.length; 
    } 

    //Needed due to methods being abstract 
    public Object getItem(int position) {return null;} 
    public long getItemId(int position) {return 0;} 

    // create a new ImageView for each item referenced by the Adapter 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ImageView imageView = (ImageView) convertView; 
     if (imageView == null) { 
      // if it's not recycled, initialize some attributes 
      imageView = new ImageView(mContext); 
      imageView.setLayoutParams(new GridView.LayoutParams(500, 500)); 
      imageView.setPadding(5, 5, 5, 5); 
     } else { 
      imageView = (ImageView) convertView; 
     } 

     //imageView.setImageResource(mThumbIds[position]); 
     Picasso.with(getActivity()) 
       .load(moviePath[position]) 
       .fit() 
       .into(imageView); 
     return imageView; 
    } 
} 

我還使用了onPostExecut內的setAdapter() e()方法。

謝謝大家的幫助= D