【问题标题】:How to correctly update RecyclerView?如何正确更新 RecyclerView?
【发布时间】:2018-08-25 21:04:48
【问题描述】:

我正在使用 SQLite 数据库来填充 RecyclerView。我想让 RecyclerView 实时更新。但我失败了。我曾尝试使用“notifyDataSetChanged()”,但它不起作用。

您能否告诉我如何通过制作“新适配器”来刷新 RecyclerView。

哪个更好“notifyDataSetChanged();”还是其他?

这是我的 RecyclerViewAdapter

package e.wolverine2.thewalkingapp;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

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


  public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {

    Context context;
    List<World> worldList = new ArrayList<>();


    public RecyclerViewAdapter() {
        //Default Constructor
    }

    public RecyclerViewAdapter(Context context, List<World> worldList) {
        this.context = context;
        this.worldList = worldList;
    }


    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;

        view = LayoutInflater.from(context).inflate(R.layout.single_row, parent, false);
        MyViewHolder viewHolder = new MyViewHolder(view);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerViewAdapter.MyViewHolder holder, int position) {

        holder.textView_Latitude.setText("Latitude : " + String.valueOf(worldList.get(position).getLatitiude()));
        holder.textView_Longitude.setText("Longitude : " + String.valueOf(worldList.get(position).getLongitude()));
        holder.textView_Time.setText("Time : " + worldList.get(position).getDate());
        holder.textView_Location.setText("Location : \n" + "NEW LOCATION!");

    }

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

    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {


        TextView textView_Latitude;
        TextView textView_Longitude;
        TextView textView_Time;
        TextView textView_Location;
        CardView cardView;


        public MyViewHolder(View view) {
            super(view);

            textView_Latitude = (TextView) view.findViewById(R.id.textView_Latitude);
            textView_Longitude = (TextView) view.findViewById(R.id.textView_Longitude);
            textView_Time = (TextView) view.findViewById(R.id.textView_Time);
            textView_Location = (TextView) view.findViewById(R.id.textView_Location);
            cardView = (CardView) view.findViewById(R.id.cardView);
        }

    }


    public void updateData(List<World> newWorldList) {

        if (newWorldList != null && newWorldList.size() > 0) {


            worldList.clear();
            worldList.addAll(newWorldList);

            new MainActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    notifyDataSetChanged();
                    Toast.makeText(context, "updateData Called!", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

**编辑:

adapter.updateData(List);

在“locationChanged(double, double)”方法中被调用。

MainActivity.class :**

public class MainActivity extends AppCompatActivity implements Tab1.OnFragmentInteractionListener, Tab2.OnFragmentInteractionListener, Tab3.OnFragmentInteractionListener {


    DBHelper helper;
    World world;
    Location location;
    GPSTracker tracker;
    RecyclerViewAdapter adapter;

    private Tab1 tab1;

    public static final String BROADCAST_ACTION = "e.wolverine2.thewalkingapp";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 123);

        MessageReciever reciever = new MessageReciever(new Message());

        Intent intent = new Intent(this, MyService.class);
        intent.putExtra("reciever", reciever);
        startService(intent);

        tracker = new GPSTracker(getApplicationContext());
        location = tracker.getLocation();
        helper = new DBHelper(getApplicationContext());
        tab1 = new Tab1();
        adapter = new RecyclerViewAdapter(getApplicationContext(), helper.getList());

        final TabLayout tabLayout = (TabLayout) findViewById(R.id.myTabLayout);
        tabLayout.addTab(tabLayout.newTab().setText("LOCATIONS"));
        tabLayout.addTab(tabLayout.newTab().setText("TOTAL DISTANCE"));
        tabLayout.addTab(tabLayout.newTab().setText("CALS"));

        tabLayout.getTabAt(0).setIcon(R.drawable.ic_list);
        tabLayout.getTabAt(1).setIcon(R.drawable.ic_person_pin);
        tabLayout.getTabAt(2).setIcon(R.drawable.ic_fitness_excercise);


        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

        //onError();

        final ViewPager viewPager = (ViewPager) findViewById(R.id.myViewPager);
        final PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(pagerAdapter);


        viewPager.setOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

                try {


                    if (tab.getPosition() == 0) {
                        adapter.updateData(new DBHelper(getApplicationContext()).getList());
                    }
                } catch (Exception e) {
                    Toast.makeText(MainActivity.this, "Main Activity " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });

    }


    public void locationChanged(double longi, double lati) {

        final Location location = new Location("");

        location.setLatitude(lati);
        location.setLongitude(longi);
        world = new World();

        String timeStamp = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date());

        world.setLongitude(location.getLongitude());
        world.setLatitiude(location.getLatitude());
        world.setDate(timeStamp);
        world.setTime(timeStamp);
        world.setLocation("Anonymous");


        helper.addRow(world);
        adapter.updateData(new DBHelper(getApplicationContext()).getList());


    }

    @Override
    public void onFragmentInteraction(Uri uri) {
    }

    public class Message {

        public void displayMessage(int resultCode, Bundle resultData) {


            try {
                double longi = resultData.getDouble("longitude");
                double lati = resultData.getDouble("latitude");

                locationChanged(longi, lati);
            } catch (Exception e) {
                Toast.makeText(MainActivity.this, "TOASTY X : " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }


        }

    }


    public void onError() {
        helper.onDropTable();
        Toast.makeText(this, "TABLE DROPED!", Toast.LENGTH_SHORT).show();
    }
}

【问题讨论】:

  • notifyDataSetChanged() 不起作用是什么意思?
  • 是的,这正是我要说的。请帮我完成它。
  • 你是不是把适配器设置为recyclerview??
  • 你能编辑你的答案并粘贴mainactivity的代码吗
  • @Chisko 是的,我是。

标签: android android-recyclerview


【解决方案1】:

我认为您只需要通知适配器 worldList 已更改。

public void updateData(List<World> newWorldList) {

    if (newWorldList != null && newWorldList.size() > 0) {


                worldList.clear();
                worldList.addAll(newWorldList);
                notifyDataSetChanged();

            }
        }

【讨论】:

  • @VoidMain 怎么一样?在您的帖子中,您正在创建 MainActivity 的一个实例,然后在 runOnUiThread() 中执行 notifydatasetchanged()。你不应该创建一个主要活动的实例并像那样调用 runonuithread
  • 我的意思是无论哪种方式它都有相同的结果,我都试过了。 notifyDataSetChange() 无论哪种方式都会被调用。但 RecyclerView 没有变化,
  • 你如何到达 RecyclerView 适配器?您可以创建一个未添加到 RecyclerView 的适配器实例。
【解决方案2】:

您实际上不需要创建MainActivity 的实例,就像这样放置

public void updateData(List<World> newWorldList) {

            if (newWorldList != null && newWorldList.size() > 0) {
                worldList.clear();
                worldList.addAll(newWorldList);
                notifyDataSetChanged();       
            }
}

它会使您的适配器刷新,但您需要从活动中调用此方法。为此,在您设置适配器的类中,您可以像这样调用此方法

adapter.updateData(list); //where adapter is the instance of your adapter and list is the new data list

编辑

我认为方法有效,问题可能出在数据集上

这一行声明新列表必须包含超过 0 个元素,如果不包含,则不会调用带有 notifydatasetchanged 的​​逻辑。请确保在调试中您得到一个不为空且包含元素的新列表

if (newWorldList != null && newWorldList.size() > 0)

【讨论】:

    【解决方案3】:

    @VoidMain,请查看下面的代码并尝试在您的代码上实现。

    public void updateData(List<World> newWorldList) {
        if(newWorldList == null || newWorldList.size() == 0)
            return;
        if(worldList != null && worldList.size() > 0)
            data.clear();
        worldList.addAll(newWorldList);
        notifyDataSetChanged();
    }
    

    【讨论】:

      【解决方案4】:

      上线

      adapter = new RecyclerViewAdapter(getApplicationContext(), helper.getList());

      做一些类似的事情:

      RecyclerView rv = (RecyclerView)findViewById(R.id.recycler_view); // &lt;- substitute 'recycler_view' for the actual id

      在我提到的第一行下面,做:

      rv.setAdapter(adapter);

      【讨论】:

        【解决方案5】:

        确保您以正确的方式实现了适配器。你可以有这样的指导:

        public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder>{
        
           private final Context mContext;
           private List<YourItem> mItemList;
        
           public YourAdapter(Context context){
              this.mContext = context;
           }
        
           // Called each time you must refresh or set the list of items in your recycler view...
           public void setItemList(List<YourItem> itemList){
              this.mItemList = itemList;
              notifyDataSetChanged();
           }
        
        
           @Override
           public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        
              Context context         = parent.getContext();
              LayoutInflater inflater = LayoutInflater.from(context);
        
              int layoutId  = R.layout.list_item_layout;
        
              View view = inflater.inflate(layoutId, parent, false);
              return new ViewHolder(view);
           }
        
           @Override
           public void onBindViewHolder(final ViewHolder holder, int position) {
              YourItem item = mItemList.get(position);
              // Render "item" values in the respective textviews, etc.
           }
        
           // Very important. Must check the null (just in case). Good practice.
           @Override
           public int getItemCount() {
              return mItemList != null ? mItemList.size() : 0;
           }
        
           public class MoviesAdapterViewHolder extends RecyclerView.ViewHolder {
              ...
           }
        }
        

        在您的片段(onCreateView)或活动(onCreate)中,只需这样做:

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        
            ...
        
            // Setting adapter
            layoutManager = new GridLayoutManager(this, 2); // You can use any LayoutManager.
            mBinding.moviesRecyclerView.setLayoutManager(layoutManager);
            mBinding.moviesRecyclerView.setHasFixedSize(true);
            adapter = new MoviesAdapter(this,this);
            mBinding.moviesRecyclerView.setAdapter(adapter);
        
            ...
        
        }
        

        当您准备好将数据加载到回收站视图时:

        // This will change the list in the adapter and "refresh" it. Remember that "setItemList" in the adapter has notifyDatasetChanged() inside.
        adapter.setItemList(moviesList); 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-07
          • 1970-01-01
          • 2018-10-14
          相关资源
          最近更新 更多