如何刷新自定义图像适配器的 GridView?

How to refresh GridView for Custom Image Adapter?

我目前正在处理一个在线 android 学习项目,并且在刷新我的网格视图时遇到问题。

我的应用最初显示一个包含多个图像的网格。单击菜单中的 刷新按钮,GridView 应填充新的 images.Also,单击任何图像,应用会转到详细信息 Activity显示当前图像 URL.

目前,我首先使用我的自定义适配器和 Picasso 使用示例图像填充 GridView。然后执行 AsyncTask,从 JSON 获取新图像 URLs。这个新图像URL 列表必须提供给我的适配器,以便网格显示新图像。

但是,我无法做到这一点。我的初始网格显示图像,单击这些图像后,我会按预期在详细信息 activity 屏幕上看到它们的 URL。但是,当我单击菜单中的 刷新 时,我没有看到新图像。我正在尝试使用 onPostExecute() 中更新的 URL 数组设置适配器。

点击旧图片时,我在细节 activity 中看到了新的 URL,但是当我点击返回时,图片仍然没有更新并且 URL 变回旧的。有时,当我滚动新图像时,应用程序会崩溃。

所以基本问题是,即使在获得新的 URLs 之后,我也无法用新图像填充 GridView。对此的任何帮助将不胜感激。谢谢,

代码片段:

public class MovieListFragment extends Fragment {
public CustomAdapter customAdapter;
public GridView gv;
public List<String> allImages=new ArrayList<String>();
public List<String> newImages=new ArrayList<String>();
public String LOG_TAG=MovieListFragment.class.getSimpleName();
public int abc=0;
public MovieListFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootview= inflater.inflate(R.layout.movie_list_fragment, container, false);


    //Fake Data Creation for 1st time GridView load.
    allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
    allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
    allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
    allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
    allImages.add("http://41.media.tumblr.com/78335e84b3b353ad60c335b24a5f267e/tumblr_nz2bke3fJ51rldeoho1_500.jpg");
    allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
    allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
    allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");
    allImages.add("http://www.pnas.org/site/misc/images/15-01065.500.jpg");

    //Set Adapter
    gv = (GridView) rootview.findViewById(R.id.gridview);
    customAdapter=new CustomAdapter(getActivity(),allImages);
    gv.setAdapter(customAdapter);

    //On Click Listener
    gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Intent intent = new Intent(getActivity(), DetailActivity.class);
            intent.putExtra("imageURL", allImages.get(position).toString());
            startActivity(intent);
        }
    });

    return rootview;
}

//My Custom Adapter
public class CustomAdapter extends BaseAdapter{

    private Context mContext;
    private List<String> myImageList;

    public CustomAdapter(Context c, List<String> finalImageList) {

       mContext = c;
       myImageList=finalImageList;
       notifyDataSetChanged();
   }

   @Override
   public int getCount() {
       return myImageList.size();
   }

   @Override
   public Object getItem(int position) {
       return myImageList.get(position);
   }

   @Override
   public long getItemId(int position) {
       return 0;
   }

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {

       ImageView imageView;
       if (convertView == null) {
           // if it's not recycled, initialize some attributes
           imageView = new ImageView(mContext);
           imageView.setLayoutParams(new GridView.LayoutParams(500, 500));
           imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
         //  imageView.setPadding(2, 2, 2, 2);
       } else {
           imageView = (ImageView) convertView;
       }

       Picasso.with(getActivity())
               .load(myImageList.get(position))
               .into(imageView);

       return imageView;
   }

}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.movie_list_fragment_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id=item.getItemId();
    if(id==R.id.action_refresh){
        updateMovieList();
        return true;
    }

    return super.onOptionsItemSelected(item);
}

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

private void updateMovieList() {
    FetchMovieDetailsTask fetchMovieDetailsTask=new FetchMovieDetailsTask();
    fetchMovieDetailsTask.execute("Popularity");
}

public class FetchMovieDetailsTask extends AsyncTask<String, Void, String[]>{
    public String LOG_TAG_SECOND=FetchMovieDetailsTask.class.getSimpleName();


    @Override
    protected String[] doInBackground(String... params) {

        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;

        // Will contain the raw JSON response as a string.
        String movieDetailJsonStr = "";
        String filterType = "";
        String api_key = "e77c4d231a4c24ffe0357b694751910c";

        if (params[0].equals("Popularity")) {
            filterType = "vote_average.desc";
        } else if (params[0].equals("Rating")) {
            filterType = "popularity.desc";
        }

        try {

            final String MOVIEDETAIL_BASE_URL = "https://api.themoviedb.org/3/discover/movie?";
            final String FILTER_PARAM = "sort_by";
            final String APP_KEY_PARAM = "api_key";

            Uri builtUri = Uri.parse(MOVIEDETAIL_BASE_URL).buildUpon()
                    .appendQueryParameter(FILTER_PARAM, filterType)
                    .appendQueryParameter(APP_KEY_PARAM, api_key).build();


            URL url = new URL(builtUri.toString());
            Log.v(LOG_TAG_SECOND, builtUri.toString());

            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // Read the input stream into a String
            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            if (inputStream == null) {
                // Nothing to do.
                return null;
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {

                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                // Stream was empty.  No point in parsing.
                return null;
            }
            movieDetailJsonStr = buffer.toString();
            Log.v(LOG_TAG_SECOND, " Movie Details JSON " + movieDetailJsonStr);

            try {
                getMovieDetailsFromJSON(movieDetailJsonStr);
            } catch (JSONException e) {
                e.printStackTrace();
            }


        } catch (IOException e) {
            Log.e(LOG_TAG, "Error ", e);
            return null;

        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e(LOG_TAG, "Error closing stream", e);
                }
            }
        }
        return null;
    }


    private String[] getMovieDetailsFromJSON(String movieDetailsJSON) throws JSONException{

        final String MOV_TITLE = "title";
        final String MOV_OVERVIEW = "overview";
        final String MOV_RATING = "vote_average";
        final String MOV_POSTER_PATH = "poster_path";

        final String MOV_LIST = "results";

        JSONObject movieListJSON = new JSONObject(movieDetailsJSON);
        JSONArray movieListArray = movieListJSON.getJSONArray(MOV_LIST);

        int numOfMovies=8;
        allImages.clear();
        String[] resultStrs = new String[numOfMovies];
        String[] resultPosters= new String[numOfMovies];

        for(int i=0; i<numOfMovies; i++){

            String title;
            String overview;
            String rating;
            String poster_path;

            JSONObject movieDetails=movieListArray.getJSONObject(i);

            overview=movieDetails.getString(MOV_OVERVIEW);
            title=movieDetails.getString(MOV_TITLE);
            rating=movieDetails.getString(MOV_RATING);
            poster_path=movieDetails.getString(MOV_POSTER_PATH);

            resultStrs[i]=title + "\n" + overview + "\n" + rating + "\n" + poster_path;
            resultPosters[i]=poster_path;
            makePosterURL(resultPosters[i]);


        }

        for (String s : resultStrs) {
            Log.v(LOG_TAG_SECOND, "MOVIE DETAILS: " + s);
        }
        return resultStrs;


    }

    private void makePosterURL(String resultPoster) {
        String baseURL="http://image.tmdb.org/t/p/w500";
        //resultPoster=resultPoster.replace("\", "");
        String finalURL="";
        finalURL=baseURL+resultPoster;
        Log.v(LOG_TAG_SECOND, "Final Poster URL " + finalURL);
        allImages.add(finalURL);
    }

    @Override
    protected void onPostExecute(String[] strings) {
        if(strings!=null){
            customAdapter=new CustomAdapter(getActivity(), allImages);
            gv.invalidateViews();
            gv.setAdapter(customAdapter);
        }
       // super.onPostExecute(strings);
    }
}

因为您总是 return null 在您的 doInBackground() 中,所以代码永远不会用更新的 lits 重置您的适配器。要更新您的更新程序,您只需调用

adapter.notifyDataSetChanged();

在你的 onPostExecuted()
顺便说一句,你的 getMovieDetailsFromJSON() return 类型 String[]doInBackgound() 一样没用,你应该把它设为无效,因为你不使用这个值。