如何正确更新RecyclerView?

时间:2018-03-16 17:52:14

标签: android android-recyclerview

我正在使用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(列表);

在“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();
    }
}

5 个答案:

答案 0 :(得分:0)

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

public void updateData(List<World> newWorldList) {

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


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

            }
        }

答案 1 :(得分:0)

您实际上并不需要像这样创建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)

答案 2 :(得分:0)

@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();
}

答案 3 :(得分:0)

在线上

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

做类似的事情:

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

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

rv.setAdapter(adapter);

答案 4 :(得分:0)

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

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);