【问题标题】:RecyclerView does not update after deleting an item from sqlite? [duplicate]从 sqlite 删除项目后 RecyclerView 不更新? [复制]
【发布时间】:2016-09-17 07:01:19
【问题描述】:

我已经从 sqlite 填充了 recyclerview。当单击每一行时,行将从 sqlite 中删除,但删除后 recyclerview 不显示更新的列表。回收站视图仅在再次启动活动后才显示更新列表。我的问题是如何在不刷新的情况下从 recyclerview 中删除项目后立即更新 recycler 视图。

以下是我的代码

SecondActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

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

public class SecondActivity extends AppCompatActivity {
    DatabaseHelpher helpher;
    List<DatabaseModel> dbList;
RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);


        helpher = new DatabaseHelpher(this);
        dbList= new ArrayList<DatabaseModel>();
        dbList = helpher.getDataFromDB();


        mRecyclerView = (RecyclerView)findViewById(R.id.recycleview);

        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new RecyclerAdapter(this,dbList);
        mRecyclerView.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged ();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_second, menu);
        return true;
    }



    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

DatabaseHelpher.java

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;

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

public class DatabaseHelpher extends SQLiteOpenHelper {
    private static final String DATABASE_NAME="student";
    private static final int DATABASE_VERSION = 1;
    private static final String STUDENT_TABLE = "stureg";
    private static final String STU_TABLE = "create table "+STUDENT_TABLE +"(name TEXT,email TEXT primary key,roll TEXT,address TEXT,branch TEXT)";

Context context;

    public DatabaseHelpher(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(STU_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        db.execSQL("DROP TABLE IF EXISTS " + STUDENT_TABLE);

        // Create tables again
        onCreate(db);
    }
/* Insert into database*/
    public void insertIntoDB(String name,String email,String roll,String address,String branch){
        Log.d("insert", "before insert");

        // 1. get reference to writable DB
        SQLiteDatabase db = this.getWritableDatabase();

        // 2. create ContentValues to add key "column"/value
        ContentValues values = new ContentValues();
        values.put("name", name);
        values.put("email", email);
        values.put("roll", roll);
         values.put("address", address);
        values.put("branch", branch);

        // 3. insert
        db.insert(STUDENT_TABLE, null, values);
        // 4. close
        db.close();
        Toast.makeText(context, "insert value", Toast.LENGTH_LONG);
        Log.i("insert into DB", "After insert");
    }
/* Retrive  data from database */
    public List<DatabaseModel> getDataFromDB(){
        List<DatabaseModel> modelList = new ArrayList<DatabaseModel>();
        String query = "select * from "+STUDENT_TABLE;

        SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query,null);

        if (cursor.moveToFirst()){
            do {
                DatabaseModel model = new DatabaseModel();
                model.setName(cursor.getString(0));
                model.setEmail(cursor.getString(1));
                model.setRoll(cursor.getString(2));
                model.setAddress(cursor.getString(3));
                model.setBranch(cursor.getString(4));

                modelList.add(model);
            }while (cursor.moveToNext());
        }


        Log.d("student data", modelList.toString());


        return modelList;
    }


    /*delete a row from database*/

    public void deleteARow(String email){
        SQLiteDatabase db= this.getWritableDatabase();
        db.delete(STUDENT_TABLE, "email" + " = ?", new String[] { email });
        db.close();
    }

}

DatabaseModel.java

public class DatabaseModel {
    private String name;
    private String roll;
    private String address;
    private String branch;
    private String email;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRoll() {
        return roll;
    }

    public void setRoll(String roll) {
        this.roll = roll;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getBranch() {
        return branch;
    }

    public void setBranch(String branch) {
        this.branch = branch;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

RecyclerAdapter.java

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
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 RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

  static   List<DatabaseModel> dbList;
    static  Context context;

    static DatabaseHelper dh;
    RecyclerAdapter(Context context, List<DatabaseModel> dbList ){
        this.dbList = new ArrayList<DatabaseModel>();
        this.context = context;
        this.dbList = dbList;
dh=new DatabaseHelper(context);
    }

    @Override
    public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_row, null);

        // create ViewHolder

        ViewHolder viewHolder = new ViewHolder(itemLayoutView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {

        holder.name.setText(dbList.get(position).getName());
        holder.email.setText(dbList.get(position).getEmail());

    }

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

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView name,email;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);
            name = (TextView) itemLayoutView
                    .findViewById(R.id.rvname);
            email = (TextView)itemLayoutView.findViewById(R.id.rvemail);
            itemLayoutView.setOnClickListener(this);

        }

        @Override
        public void onClick(View v) {
           dh.delete(dbList.get(getAdapterPosition()).getEmail);


            Toast.makeText(RecyclerAdapter.context, "you have clicked Row " + getAdapterPosition(), Toast.LENGTH_LONG).show();
        }
    }
}

我尝试使用 mAdapter.notifyDataSetChanged (); 更新 recyclerview,但它对我不起作用。请建议我。谢谢

【问题讨论】:

  • 您需要使用“notifyItemRemoved(position);”修改适配器这段代码。从数据库中删除后添加这个即可。
  • @SurenderKumar.ya 我也试过那个。它不适合我
  • 忘记告诉你在删除表单适配器之前还需要从 arraylist 中删除位置。试试看

标签: android sqlite listview android-recyclerview


【解决方案1】:

从您的数组列表和数据库中删除数据,然后通知您的列表将更新。

从数据库中删除数据并在删除后从数据库中获取数据并用新数据重新加载您的数组列表将完成您的工作

dbList.remove(getAdapterPosition());
notifyDataSetChanged();
//or use this for better perfomance.
notifyItemRemoved(getAdapterPosition());

在remove方法中传递位置

【讨论】:

    【解决方案2】:

    您正在从数据库中删除数据,而不是从您已获取所有数据的列表中删除数据,因此在您从列表中删除数据之前,即使它已被删除,它也会显示给您。所以你需要改变你的删除方法,还需要从列表中删除数据。

    检查下面更新的删除方法。

          @Override
          public void onClick(View v) {
                dh.delete(dbList.get(getAdapterPosition()).getEmail);
    
                // These two lines added for remove data from adapter also.
                dbList.remove(getAdapterPosition());
                notifyDataSetChanged();
    
    
                Toast.makeText(RecyclerAdapter.context, "you have clicked Row " + getAdapterPosition(), Toast.LENGTH_LONG).show();
        }
    

    【讨论】:

    • @Vickyexpert。感谢您的回答。我会尝试。假设如果我对 sqlite 进行更新而不是删除,那么我必须使用哪种方法?
    • 您可以为第一个做两件事,如果将您的适配器放在同一个 activtiy 类中,以便您可以编辑列表然后将其设置在适配器中,或者在单击调用另一个活动并传递时进行第二件事参数中的位置,然后在下一个活动中使用该位置获取特定数据,允许用户编辑并单击更新按钮编辑数据并回调此主要活动,以便它直接向您显示更新的列表。
    • @vision 关键是您的 RecyclerView 不会直接显示数据库中的内容,而是显示列表中的内容。如果您更改了数据库中的某些内容但未更改列表中的内容,则显示不会更改。无论您在数据库中进行什么更改,您都需要对 List 进行适当的更改,或者您需要再次查询数据库以获取新的 List。
    【解决方案3】:

    使用

    从 arrayList 中删除列表数据
     arrayList.remove(position);
    

    并使用更新您的适配器,

     mAdapter.notifyDataSetChanged ();
    

    【讨论】:

      【解决方案4】:

      //在Adapter类中定义一个接口

      private static ItemClickListener itemClickListener;
      
      public interface ItemClickListener {
          void onItemClick(int position, View v);
      }
      

      还有一个方法

      public void setOnItemClickListener(ItemClickListener myClickListener) {
          RecyclerAdapter.itemClickListener = myClickListener;
      }
      

      在viewHolder的onClick方法中

       @Override
          public void onClick(View v) {
             dh.delete(dbList.remove(getAdapterPosition()).getEmail);
             itemClickListener.onItemClick(getLayoutPosition(), v);
      
              Toast.makeText(RecyclerAdapter.context, "you have clicked Row " + getAdapterPosition(), Toast.LENGTH_LONG).show();
          }
      

      在 Activity 的 onCreate() 或 onResume() 方法中

       mAdapter.setOnItemClickListener(new RecyclerAdapter.ItemClickListener() {
              @Override
              public void onItemClick(int position, View v) {
                  mAdapter.notifyDataSetChanged();
              }
          });
      

      【讨论】:

        【解决方案5】:

        尝试重新加载信息。

        改变这个

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case android.R.id.home:
                    finish();
                    return true;
            }
            return super.onOptionsItemSelected(item);
        }
        

        到这里:

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
        
            dbList = helpher.getDataFromDB();
            mAdapter = new RecyclerAdapter(this,dbList);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.notifyDataSetChanged ();
        
            switch (item.getItemId()) {
                case android.R.id.home:
                    finish();
                    return true;
            }
            return super.onOptionsItemSelected(item);
        }
        

        每次点击都会在 Recycler Vuew 重新加载信息。

        【讨论】:

        • 大声笑,兄弟,你确定你告诉了什么......在哪个项目的点击上,这个代码会被触发?它根本不会......
        • 谢谢鲁本。你刚刚给出了一个想法。现在在我的代码中,我只显示了 recyclerview 数据两次。一种来自外部按钮点击,另一种来自内部按钮点击。所以值会在插入新值后动态变化,并且在我看来会有所反应
        【解决方案6】:

        您只需要在onClick 方法中通知适配器删除了一项即可

        @Override
        public void onClick(View v) {
            notifyItemRemoved(this.getLayoutPosition());
        }
        

        【讨论】:

          【解决方案7】:

          使用notifyItemRemoved() 代替notifyDataSetChanged()

          【讨论】:

            【解决方案8】:

            这样做

            builder.setNeutralButton("Delete", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    PersonDBHelper dbHelper = new PersonDBHelper(mContext);
                    dbHelper.deletePersonRecord(person.getId(), mContext);
            
                    mPeopleList.remove(position);
                    mRecyclerV.removeViewAt(position);
                    notifyItemRemoved(position);
                    notifyItemRangeChanged(position, mPeopleList.size());
                    notifyDataSetChanged();
                }
            });
            

            并在回收列表中使用 On restart 方法

            【讨论】:

              【解决方案9】:

              您可以在 Activity 中执行删除操作后调用 recreate(),以便刷新 Activity。这个对我有用。希望这对您也有用。

              【讨论】:

                【解决方案10】:

                当sqlite中的数据发生变化时,有一种完全不同的方法来更新recyclerview。这是通过使用游标。

                你可能想看这个视频:https://www.youtube.com/playlist?list=PLrnPJCHvNZuBMJmll0xy2L2McYInT3aiu

                代码可在:https://codinginflow.com/tutorials/android/sqlite-recyclerview/part-1-layouts-contract-sqliteopenhelper

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-10-02
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-01-15
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多