如何使用RecyclerView Adapter

时间:2019-03-26 18:00:14

标签: android android-recyclerview android-sqlite recycler-adapter

我只是想使用RecyclerView来创建一个列表,其中每个列表项都将包含一个复选框按钮。因此,当用户单击复选框时,它将替换表格列的值,例如列国家/地区获取值“ A”,而未选中则将国家/地区列的值从“ A”替换为“ B”或其他任何值。

有人可以帮我吗?关于使用Recyclable在SQLite数据库中添加数据以及其他类似方法的任何建议都将非常有帮助。

下面我添加了我的代码供您参考,并提前致谢。

我的DatabaseHelper类

    package com.hfad.ressql;

    import android.content.ContentValues;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import com.hfad.ressql.DatabaseContractor.*;

    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.List;

    public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "workers.db";
    private static final int DATABASE_VERSION =7;

    SQLiteDatabase db;

    public DatabaseHelper( Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
     this.db=db;

     final String SQL_CREATE_TBALE="CREATE TABLE " +  EmployeeDetails.TABLE_NAME + "(" + EmployeeDetails._ID +" INTEGER PRIMARY KEY  AUTOINCREMENT, "+
             EmployeeDetails.COLUMN_FIRSTNAME+" TEXT,  "+EmployeeDetails.COLUMN_LASTNAME+" TEXT, "+EmployeeDetails.COLUMN_COUNTRY+" TEXT)";

     db.execSQL(SQL_CREATE_TBALE);
     fillquestion();

    }

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



        db.execSQL("DROP TABLE IF EXISTS " + EmployeeDetails.TABLE_NAME);
        onCreate(db);

    }


    public void fillquestion(){
    DataModel o4 = new DataModel("Earth","Soil","B");
    IntertData(o4);
    DataModel o5 = new DataModel("Sun","Light","B");
    IntertData(o5);
    DataModel o6 = new DataModel("Moon","Rock","B");
    IntertData(o6);

    }

    public void IntertData (DataModel data){

        ContentValues contentValues = new ContentValues();
        contentValues.put(EmployeeDetails.COLUMN_FIRSTNAME,     data.getFirstName());
        contentValues.put(EmployeeDetails.COLUMN_LASTNAME,   data.getLastName());
        contentValues.put(EmployeeDetails.COLUMN_COUNTRY, data.country);
        db.insert(EmployeeDetails.TABLE_NAME,null,contentValues);
    }

    public List<DataModel> object1() {
        ArrayList<DataModel> details = new ArrayList<DataModel>();
        db = getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + EmployeeDetails.TABLE_NAME, null );
        if (cursor.moveToFirst()) {

            do {
                DataModel object2 = new DataModel();
                object2.setFirstName(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_FIRSTNAME)));
                object2.setLastName(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_LASTNAME)));
                object2.setCountry(cursor.getString(cursor.getColumnIndex(EmployeeDetails.COLUMN_COUNTRY)));


                details.add(object2);

            } while (cursor.moveToNext());
        }
        cursor.close();
        return details;
    }
}

这是我的DataModel类

    package com.hfad.ressql;

    public class DataModel {

    public String FirstName;
    public String LastName;
    public String country;



    public DataModel() {
    }

    public DataModel(String firstName, String lastName, String country) {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.country = country;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String firstName) {
        FirstName = firstName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String lastName) {
        LastName = lastName;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
     }

数据库构造器

       public final class DatabaseContractor {

       private DatabaseContractor (){}

        public static class EmployeeDetails implements BaseColumns {
        public static final String TABLE_NAME="employy";
        public static final String COLUMN_FIRSTNAME="First_Name";
        public static final String COLUMN_LASTNAME="Last_Name";
        public static final String COLUMN_COUNTRY="Country";
        public static final String COLUMN_FAVO="mfav";


        }

        }

回收站适配器

我在这里努力解决问题。我所需要的是,如果我单击复选框,则将在数据库中更新一个给定的值,同时将选中该复选框,直到用户取消选中它为止。当用户取消选中它时,数据库将用新值替换以前的值。实际上,我只是试图在表列中包含值,以便可以将其用作收藏夹或书签列表。

    public class RecycAdapter extends       
    RecyclerView.Adapter<RecycAdapter.ViewHolder> {

    List<DataModel> dotamodeldataArraylist;
    Context context;
    SQLiteDatabase db;
    DatabaseHelper helper;
    ContentValues contentValues;
    Cursor cursor;

    public RecycAdapter(List<DataModel> dotamodeldataArraylist,Context context) {
        this.dotamodeldataArraylist=dotamodeldataArraylist;
        this.context=context;
    }

    @Override
    public ViewHolder onCreateViewHolder( ViewGroup parent, int ViewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemlist,parent,false);

        return new ViewHolder(view);
    }

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

        DataModel obj3= dotamodeldataArraylist.get(position);
        holder.Fnam.setText(obj3.getFirstName());
        holder.Lname.setText(obj3.getLastName());
        holder.Country.setText(obj3.getCountry());
        holder.fav.();
      holder.fav.setChecked(fav);
      final int currentPosition = position;



           final boolean fav = 0==0;
      holder.fav.setChecked(fav);
      final int currentPosition = position;



        holder.fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                if(holder.fav.isChecked()){
                   try {
                       contentValues = new ContentValues();
                       contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY, "B");
                       db.update("DRINK", contentValues, "id_=?", new String[]{Integer.toString(currentPosition)});
                   } catch (SQLException e){
                       Toast.makeText(context,"error" + position , Toast.LENGTH_LONG).show();

                   }

                    Toast.makeText(context,"checked " + position , Toast.LENGTH_LONG).show();

                } if(!holder.fav.isChecked()){
                    Toast.makeText(context,"not checked" + position , Toast.LENGTH_LONG).show();
                }



            }
        });






    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView Fnam,Lname,Country;
        CheckBox fav;
        RelativeLayout relativeLayout;


        public ViewHolder(View itemView) {
            super(itemView);

            Fnam = itemView.findViewById(R.id.name1);
            Lname = itemView.findViewById(R.id.city1);
            Country = itemView.findViewById(R.id.country1);
            fav=itemView.findViewById(R.id.chk);
            relativeLayout = (RelativeLayout)     itemView.findViewById(R.id.layout);

        }
    }


    }

查看课程

查看所有课程

    public class Viewall extends AppCompatActivity {

    RecyclerView recyclerView;
    DatabaseHelper databaseHelper;
    RecycAdapter recycAdapter;
    List<DataModel> dotamodeldataArraylist;
    Context context;
    Button show;


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

        show = findViewById(R.id.view);
        recyclerView=findViewById(R.id.recycle);

        databaseHelper =new DatabaseHelper(this);
        dotamodeldataArraylist = new ArrayList<DataModel>();
        dotamodeldataArraylist=databaseHelper.object1();
        recycAdapter =new RecycAdapter(dotamodeldataArraylist,this);
        RecyclerView.LayoutManager reLayoutManager =new            
        LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(reLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(recycAdapter);

2 个答案:

答案 0 :(得分:1)

我相信以下内容可以满足您的要求。

代码有很多问题。主要问题之一是您希望该职位与 id (也就是您的 _id 列)相关。

列表中第一项的位置为 0 ,除非您强制/专门设置值为0,即 rowid 列的别名(您的 _id 列是rowid列的别名),分配的第一个值将是1,然后可能是2,然后可能是3 ...........

因此,最佳位置比ID少1。

如果删除了一行,则除最后一行外,位置将减少一个,直到通过已删除的行为止,然后位置将比该行ID小2。删除次数更多,位置和ID之间的关联更加复杂。我想有人可以提出一个简单的转换方法,但简单的方法是确保DataModel具有相应的 _id 列。

因此应更改 DataModel.java 使其包含ID的成员/变量,因此使用了以下内容:-

public class DataModel {

    public String FirstName;
    public String LastName;
    public String country;

    public long id; //<<<<<<<<<< ADDED also added gettter and setter

    public DataModel() {
    }

    public DataModel(String firstName, String lastName, String country) {
        this(firstName,lastName,country,-1);
    }

    //<<<<<<<<<< ADDED so ID can be set
    public DataModel(String firstName, String lastName, String country, long id) {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.country = country;
        this.id = id;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String firstName) {
        FirstName = firstName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String lastName) {
        LastName = lastName;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }
}
  • 查看评论以了解变化

由于需要从数据库中提取ID,因此在 DatabaseHelper.java 中更改了object1方法(还进行了其他一些更改),使用了以下内容:-

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "workers.db";
    private static final int DATABASE_VERSION =7;

    SQLiteDatabase db;

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        this.db=db; //<<<<<<< WRONG PLACE as onCreate only ever runs when there is no database

        final String SQL_CREATE_TBALE="CREATE TABLE " +  DatabaseContractor.EmployeeDetails.TABLE_NAME + "(" + DatabaseContractor.EmployeeDetails._ID +" INTEGER PRIMARY KEY  AUTOINCREMENT, "+
                DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME+" TEXT,  "+ DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME+" TEXT, "+ DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY+" TEXT)";

        db.execSQL(SQL_CREATE_TBALE);
        fillquestion();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DatabaseContractor.EmployeeDetails.TABLE_NAME);
        onCreate(db);
    }


    public void fillquestion(){
        IntertData(new DataModel("Earth","Soil","B"));
        IntertData(new DataModel("Sun","Light","B"));
        IntertData(new DataModel("Moon","Rock","B"));
    }

    public void IntertData (DataModel data){

        ContentValues contentValues = new ContentValues();
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME,data.getFirstName());
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME,data.getLastName());
        contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY,data.country);
        db.insert(DatabaseContractor.EmployeeDetails.TABLE_NAME,null,contentValues);
    }

    public List<DataModel> object1() {
        ArrayList<DataModel> details = new ArrayList<>();
        //db = getReadableDatabase(); db has already been set when database was instantiated/constructed
        Cursor cursor = db.rawQuery("SELECT * FROM " + DatabaseContractor.EmployeeDetails.TABLE_NAME, null );
        while (cursor.moveToNext()) {
            details.add(new DataModel(
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_FIRSTNAME)),
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_LASTNAME)),
                    cursor.getString(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY)),
                    cursor.getLong(cursor.getColumnIndex(DatabaseContractor.EmployeeDetails._ID)) //<<<<<<<<< Added so id is available
            ));
        }
        cursor.close();
        return details;
    }
}

对RecycAdapter.java进行了相当广泛的更改,使用了以下内容:-

public class RecycAdapter extends RecyclerView.Adapter<RecycAdapter.ViewHolder> {

    List<DataModel> dotamodeldataArraylist;
    Context context;
    SQLiteDatabase db;
    DatabaseHelper helper;
    ContentValues contentValues;

    public RecycAdapter(List<DataModel> dotamodeldataArraylist,Context context) {
        this.dotamodeldataArraylist=dotamodeldataArraylist;
        this.context=context;
        helper = new DatabaseHelper(context);
        db = helper.getWritableDatabase();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int ViewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemlist,parent,false);
        return new ViewHolder(view);
    }

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

        //DataModel obj3= dotamodeldataArraylist.get(position); //<<<<<<<<<< NOT NEEDED
        holder.Fnam.setText(dotamodeldataArraylist.get(position).getFirstName());
        holder.Lname.setText(dotamodeldataArraylist.get(position).getLastName());
        holder.Country.setText(dotamodeldataArraylist.get(position).getCountry());
        holder.fav.setChecked(false); //<<<<<<<<< not stored so initially set to false

        holder.fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String newcountry = "B";
                if(holder.fav.isChecked()){
                    if (dotamodeldataArraylist.get(position).getCountry().equals("B")) {
                        newcountry  = "A";
                    }
                    contentValues = new ContentValues();
                    contentValues.put(DatabaseContractor.EmployeeDetails.COLUMN_COUNTRY, newcountry);
                    if (db.update(
                            DatabaseContractor.EmployeeDetails.TABLE_NAME,
                            contentValues,
                            DatabaseContractor.EmployeeDetails._ID +"=?",
                            new String[]{String.valueOf(dotamodeldataArraylist.get(position).getId())}
                            ) > 0) {
                        dotamodeldataArraylist.get(position).setCountry(newcountry);
                        notifyItemChanged(position);
                        Toast.makeText(context,
                                "checked and updated " +
                                        position+ dotamodeldataArraylist.get(position).getFirstName() +
                                        " ID is " + String.valueOf(dotamodeldataArraylist.get(position).getId()),
                                Toast.LENGTH_LONG
                        ).show();
                    } else {
                        Toast.makeText(context,"error" + position , Toast.LENGTH_LONG).show();
                    }
                } else {
                    Toast.makeText(context,"not checked" + position , Toast.LENGTH_LONG).show();
                }
            }
        });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView Fnam,Lname,Country;
        CheckBox fav;

        public ViewHolder(View itemView) {
            super(itemView);
            Fnam = itemView.findViewById(R.id.name1);
            Lname = itemView.findViewById(R.id.city1);
            Country = itemView.findViewById(R.id.country1);
            fav = itemView.findViewById(R.id.chk);
        }
    }
}

最后对Viewall.java进行了一些小的更改,使用了以下内容:-

public class Viewall extends AppCompatActivity {

    RecyclerView recyclerView;
    DatabaseHelper databaseHelper;
    RecycAdapter recycAdapter;
    List<DataModel> dotamodeldataArraylist;
    Button show;

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

        show = findViewById(R.id.view);
        recyclerView = findViewById(R.id.recycle);

        databaseHelper = new DatabaseHelper(this);
        dotamodeldataArraylist = databaseHelper.object1();
        recycAdapter = new RecycAdapter(dotamodeldataArraylist, this);
        RecyclerView.LayoutManager reLayoutManager = new
                LinearLayoutManager(this);
        recyclerView.setLayoutManager(reLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(recycAdapter);
    }
}

结果

请注意,布局可能有所不同,但是您的布局应该可以工作并相应地更改显示方式

首次运行时:-

enter image description here

点击 Sun

的复选框后

enter image description here

再次单击并返回到B国,依此类推。

  • 请注意,复选框未翻转,这对于正确显示更改的数据(国家/地区)而言是个问题,因为notifyItemChanged会重新使用列表,因此将复选框设置为false。您需要将复选框的值存储在某个地方(总之,您应该以这种方式使用复选框)。

关闭应用程序并重新启动将保留所做的更改,从而确认已对数据库进行了更改。

答案 1 :(得分:0)

在@MiKe的代码之上,我刚刚在onClickListener内的RecyclerAdapter中进行了一些更改以保存复选框状态,并在dataModel类中将 isChecked作为布尔值添加了。现在它可以正常工作了。

   holder.chkbox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                Values = new ContentValues();
                Values.put(DatabaseContractor.EmployeeDetails.COLUMN_FAVORITE,holder.chkbox.isChecked());
                try{ db.update(DatabaseContractor.EmployeeDetails.TABLE_NAME,
                        Values,
                        DatabaseContractor.EmployeeDetails._ID + "=?",
                        new String[]{String.valueOf(dotamodeldataArraylist.get(position).getId())});

                } catch (SQLException e){
                    Toast.makeText(context,"Error"+position,Toast.LENGTH_LONG).show();
                }
        }
    });

再次感谢麦克,您的指导方针很棒。现在,我可以将复选框状态直接保存在sqlite数据库中。