如何更新RecyclerView-notifyDataSetChanged() [英] How to Update RecyclerView - notifyDataSetChanged()

查看:77
本文介绍了如何更新RecyclerView-notifyDataSetChanged()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个活动,其中显示一个垂直的RecyclerView列表,其中包含多个类别项目.此列表中的每个项目都是一个类别,其中显示类别标题"及其对应的图像ID".拥有此RecyclerView的活动是用户在移动设备上启动应用程序后出现的第一个活动.此外,商品类别信息是通过JSON获取的,其中我利用"Volley"库在Web上的URL处获取数据.我的问题是,即使完美地在网络上获取了信息,我的RecyclerView仍显示未填充且为空.我怀疑这是由于以下原因造成的:

I have an activity which displays a vertical RecyclerView list containing multiple category items. Each item in this list is a category which displays the "category title" and its corresponding "image id". The activity holding this RecyclerView is the first activity which appears after the user has launched the app on the mobile. Additionally, the item category information is being acquired via JSON where I make use of the "Volley" library to fetch the data at a URL on the web. My problem is that my RecyclerView shows unpopulated and empty even though the information is being fetched on the web perfectly. I suspect this is happening due to the following:

  • 用户启动应用程序
  • OnCreate显示RecyclerView
  • 已获取JSON feed
  • RecyclerView显示为空,因为JSON提取过程在后台进行,并且一旦提取数据就永远不会更新RecyclerView.

一旦JSON请求完成,如何更新RecyclerView以显示所有项目?我听说在RecyclerView适配器中使用 notifyDataSetChanged(),但我不知道如何利用此功能,最重要的是,不知道如何在我的代码中放置此功能.

How can I update the RecyclerView to display all the items once the JSON request has been completed? I heard of using the notifyDataSetChanged() in the RecyclerView adapter but I do not know how to make use of this feature and most importantly where to place it in my code.

下面是我的代码.在这种情况下如何执行RecyclerView更新的任何详细帮助将不胜感激.

Below is my code. Any detailed help on how to perform a RecyclerView update under these circumstances would be greatly appreciated.

活动

package example.co.uk.vapp;

import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import example.co.uk.vapp.adapters.GroupAdapter;
import example.co.uk.vapp.utils.RecyclerItemClickListener;

public class CategoryListActivity extends AppCompatActivity {

    // Declare variables
    private RecyclerView mRecyclerView;
    private GridLayoutManager mGridLayoutManager;

    // Tag for logging possible errors onto the Log
    private static String TAG = CategoryListActivity.class.getSimpleName();

    // Progress dialog
    private ProgressDialog pDialog;

    // JSON Array response url - ****fictitious url****
    private static final String URL = "https://www.someurl.com";

    // JSON Array containing the response
    static JSONArray jsonArrayResponse;
    // Json Object containing the category fields such as title and image-id
    static JSONObject category;
    // ArrayList containing the category titles
    static ArrayList<String> categoryTitles;
    // ArrayList containing the category image ids
    private ArrayList<String> categoryImageId;
    static GroupAdapter groupAdapter;

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

        // Set layout
        setContentView(R.layout.activity_category_list);

        // Initialize ArrayList to contain category titles
        categoryTitles = new ArrayList<String>();
        categoryImageId = new ArrayList<String>();

        // Reference variable with layout view
        mRecyclerView = (RecyclerView) findViewById(R.id.cardList);

        // Use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // Display under one column
        mGridLayoutManager = new GridLayoutManager(this, 1);
        mRecyclerView.setLayoutManager(mGridLayoutManager);
        // Set orientation
        mGridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mGridLayoutManager);

        // Create list of "Group" type
        final List<Group> groups = new ArrayList<Group>();

        for (int i = 0; categoryTitles.size() < i && categoryImageId.size() < i; i++) {
            String categoryName = categoryTitles.get(i);
            int categoryImage = Integer.getInteger(categoryImageId.get(i));

            groups.add(new Group(categoryName, categoryImage));
        }

        // Set Adapter
        groupAdapter = new GroupAdapter(groups);
        mRecyclerView.setAdapter(groupAdapter);

        // Create click listener for each item on the list
        mRecyclerView.addOnItemTouchListener(
                new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
                    @Override
                    public void onItemClick(View view, int position) {

                        Intent intent = new Intent(CategoryListActivity.this, groups.get(position).getClass());
                        startActivity(intent);
                    }
                })
        );

        // Shows message to user while makeJsonObjectRequest() is still running
        pDialog = new ProgressDialog(this);
        pDialog.setMessage("Getting exchange rates...");
        pDialog.setCancelable(false);

        // Retrieves JSON format exchange rates from Yahoo Finance
        makeJsonArrayRequest();
    }

    private void makeJsonArrayRequest() {

        // Show dialog while the request is made
        showpDialog();

        final JsonArrayRequest jsonArrayReq = new JsonArrayRequest(URL,
                new Response.Listener<JSONArray>() {

                    @Override
                    public void onResponse(JSONArray response) {

                        // Log response
                        Log.d(TAG, response.toString());

                        // Set "response" to jsonArrayResponse global variable so that we can use it on other methods in this class
                        jsonArrayResponse = response;

                        try {
                            // Get array with all categories (raw)

                            for (int i = 0; i < jsonArrayResponse.length(); i++) {
                                category = jsonArrayResponse.getJSONObject(i);

                                String title = category.getString("category-localized-title");
                                categoryTitles.add(title);

                                String imageId = category.getString("product-category-image-id");
                                categoryImageId.add(imageId);
                            }

                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toast.makeText(gevapplicationContext(),
                                    "Error: " + e.getMessage(), 
                                    Toast.LENGTH_LONG).show();
                        }

                        for (int i = 0; i < categoryTitles.size(); i++) {
                            Log.i("categoryTitles", categoryTitles.get(i).toString());
                            Log.i("categoryImageIds", categoryImageId.get(i).toString());
                        }

                        // Hide dialog after information has been requested
                        hidepDialog();
                        }


                    }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {

                // Warn user
                Toast.makeText(gevapplicationContext(),
                        "No internet connection", Toast.LENGTH_LONG).show();

                // Log error
                Log.e("test", error.getMessage());

                // hide the progress dialog
                hidepDialog();
            }
        });

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(jsonArrayReq);
    }

    /**
     * Method for showing dialog
     */
    private void showpDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    /**
     * Method for hiding dialog
     */
    private void hidepDialog() {
        if (pDialog.isShowing())
            pDialog.dismiss();
    }
}

RecyclerView适配器

package example.co.uk.vapp.adapters;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

import example.co.uk.vapp.Group;
import example.co.uk.vapp.R;

public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.GroupViewHolder> {

    private List<Group> groupList;

    public GroupAdapter(List<Group> groupList) {
        this.groupList = groupList;
    }

    @Override
    public int getItemCount() {
        return groupList.size();
    }

    @Override
    public void onBindViewHolder(GroupViewHolder holder, int position) {

        Group group = groupList.get(position);
        holder.vGroupTitle.setText(group.getGroupTitle());
        holder.vGroupImage.setImageResource(group.getGroupImage());
    }

    @Override
    public GroupViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.group_list_card_layout, parent, false);
        return new GroupViewHolder(itemView);
    }

    // Create the ViewHolder class "pattern"
    public static class GroupViewHolder extends RecyclerView.ViewHolder {
        protected TextView vGroupTitle;
        protected ImageView vGroupImage;

        public GroupViewHolder(View v) {
            super(v);

            vGroupTitle = (TextView) v.findViewById(R.id.title);
            vGroupImage = (ImageView) v.findViewById(R.id.image);
        }
    }
}

推荐答案

在适配器中,声明一个方法,一旦获取新的或初始的数据集,便可以使用该方法来更新适配器.它应该看起来像这样:

In your adapter, declare a method with which you will update the adapter once you fetched the new or initial data set. It should look something like this:

public void swapDataSet(list<Group> newData){

 this.groupList = newData;

 //now, tell the adapter about the update
 notifyDataSetChanged();

}

上面的方法可以工作,但是并不一定是进行后续更改的最有效方法,因为适配器将在整个数据集都已更改的情况下更新所有项目.首次设置适配器后,使用更具体的更改通知(例如 notifyItemInsered(int pos) notifyItemDeleted(int pos))会更好,更高效.,如果可能的话.这样一来,您也可以毫不费力地获得精美的动画.

The above method will work, but it won't necessary be the most efficient way of doing it for subsequent changes, because the adapter will update all the items assuming the entire dataset has changed. Once your adapter is set for the first time, it is better, and more efficient, to use more specific change notifications like notifyItemInsered(int pos), notifyItemDeleted(int pos), etc if possible. This way you will also get nice animations with no extra effort on your part.

更具体地说,在您的情况下,您要在没有任何标题或类别之前更新组.为什么不这样做:

More specifically, in your case, you are updating the groups before there are any titles or categories. Why not do this:

for (int i = 0; i < jsonArrayResponse.length(); i++) {
    category = jsonArrayResponse.getJSONObject(i);

    String title = category.getString("category-localized-title");

    String imageId = category.getString("product-category-image-id");


    categories.add(new Group(title, imageId));
}

//now that you have fresh groups
GroupAdapter.swapDataSet(groups);

这篇关于如何更新RecyclerView-notifyDataSetChanged()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆