Android 适配器只获取最后输入的数据

Android Adapter only fetching the last entered data

我试着环顾四周,但似乎找不到可以解决问题的答案。 这是我正在做的过程:

1: 用户在警告对话框中输入数据

2:数据发送到 sql。

3: Adapter 运行,获取数据并放入 cardview。

4:显示卡片视图(根据输入的数量堆叠)。

没有计划的,正在输出的数据会覆盖所有先前的输入,并使用最新信息更新所有卡片视图。

EG:输入 1:测试 1,输入 2:测试 2。输出将是测试 2 的 2 个卡片视图。

联系Activity

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.sp.R;

public class Contacts extends AppCompatActivity {

    private Button newContact;
    private AlertDialog.Builder builder;
    private AlertDialog dialog;
    private RecyclerView recyclerView;

    private ContactDatabaseHelper helper;
    private ContactAdapter mAdapter;

    private EditText new_contact_name;
    private EditText new_contact_number;
    private EditText new_contact_relation;
    private Button button_create_contact;
    private Button button_cancel_create;

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

        helper = new ContactDatabaseHelper(this);

        recyclerView = findViewById(R.id.contact_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new ContactAdapter(this,getAllItems());
        recyclerView.setAdapter(mAdapter);

        newContact = findViewById(R.id.contact_button);
        // New Contact Button
        newContact.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                builder = new AlertDialog.Builder(Contacts.this);
                builder.setTitle("Create New Contact");
                builder.setCancelable(false);
                View view = LayoutInflater.from(Contacts.this).inflate(R.layout.new_contact_dialog,null,false);
                CreateDialog(view);
                builder.setView(view);
                dialog = builder.create();
                dialog.show();
            }
        });

    }

    private void CreateDialog(View view) {

        // ContactDialog ID's
        new_contact_name = view.findViewById(R.id.new_contact_name);
        new_contact_number = view.findViewById(R.id.new_contact_number);
        new_contact_relation = view.findViewById(R.id.new_contact_relation);
        button_create_contact = view.findViewById(R.id.button_create_contact);
        button_cancel_create = view.findViewById(R.id.button_cancel_create);

        button_create_contact.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                        // Get String of Name, Number, Relationship
                        String contactNameStr = new_contact_name.getText().toString();
                        String contactNumberStr = new_contact_number.getText().toString();
                        String contactRelationStr = new_contact_relation.getText().toString();

                        // Insert into ContactTable
                        helper.insertContactDatabase(contactNameStr,contactNumberStr,contactRelationStr);
                        mAdapter.swapCursor(getAllItems());

                        // Outputs a Toast
                        Toast.makeText(Contacts.this, "Contact Created", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
            }
        });

        button_cancel_create.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dialog.dismiss();
            }
        });

    }

    private Cursor getAllItems(){
        return helper.getContactDatabase();
    }

}

接触适配器

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.sp.R;

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.MyHolder>{

    private Context mContext;
    private Cursor c;
    private ContactDatabaseHelper helper;

    public ContactAdapter(Context context,Cursor cursor) {

        mContext = context;
        c = cursor;
        helper = new ContactDatabaseHelper(mContext);
    }

    public static class MyHolder extends RecyclerView.ViewHolder{

        private TextView contact_name;
        private TextView contact_number;
        private TextView contact_relation;

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

            contact_name = itemView.findViewById(R.id.contact_list_name_item);
            contact_number = itemView.findViewById(R.id.contact_list_number_item);
            contact_relation = itemView.findViewById(R.id.contact_list_relation_item);
        }
    }

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(mContext).inflate(R.layout.contact_list,parent,false);

        return new MyHolder(view);
    }

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

        c.moveToFirst();

        holder.contact_name.setText(helper.getContactName(c));
        holder.contact_number.setText(helper.getContactNumber(c));
        holder.contact_relation.setText(helper.getContactRelation(c));

    }

    @Override
    public int getItemCount() {

        return c.getCount();
    }

    public void swapCursor(Cursor newCursor){
        if (c != null){
            c.close();
        }

        c = newCursor;

        if (newCursor != null){
            notifyDataSetChanged();
        }
    }

}

联系数据库

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


public class ContactDatabaseHelper extends SQLiteOpenHelper {

    public static String DATABASE_NAME = "contactlist.db";
    private static final int SCHEMA_VERSION = 1;

    public ContactDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, SCHEMA_VERSION); }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL("CREATE TABLE contact_table( name TEXT, number TEXT , relation TEXT);");

    }

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

    // Adds data into Contact database
    public void insertContactDatabase (String contact_name, String contact_number, String contact_relation) {
        ContentValues cv = new ContentValues();

        cv.put("name", contact_name);
        cv.put("number", contact_number);
        cv.put("relation", contact_relation);

        getWritableDatabase().insert("contact_table", "name", cv);
    }

    // Read Contact database
    public Cursor getContactDatabase() {
        return  (getReadableDatabase().rawQuery(
                "SELECT name, number, relation  FROM contact_table ORDER BY  + name", null));
    }

    // Delete Contact database
    public Integer deleteContactDatabase () {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete("contact_table",null,null);

    }

    public String getContactName (Cursor c){ return (c.getString(0)); }

    public String getContactNumber (Cursor c){ return (c.getString(1)); }

    public String getContactRelation (Cursor c){ return (c.getString(2)); }
}

联系人

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/contact_background"
    tools:context=".Contact.Contacts">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/contact_recycler_view"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_above="@id/contact_button"
                    android:layout_marginTop="10dp"
                    android:scrollbars="vertical">

                </androidx.recyclerview.widget.RecyclerView>

                <Button
                    android:id="@+id/contact_button"
                    android:layout_width="150dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginTop="10sp"
                    android:layout_marginBottom="10sp"
                    android:background="#43464B"
                    android:text="New Contact"
                    android:textAlignment="center"
                    android:textColor="#FFFFFF"
                    android:textSize="18sp" />
            </LinearLayout>
        </ScrollView>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

contact_list (Cardview)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/list_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardBackgroundColor="#FFEAB8"
    app:cardCornerRadius="15dp"
    app:cardElevation="5dp"
    app:cardUseCompatPadding="true">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="#00ACEE"
        app:cardCornerRadius="5dp"
        app:cardElevation="15dp"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:id="@+id/contact_layout_name"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:text="Name"
                android:textAlignment="center"
                android:textColor="#E6E6E6"
                android:textSize="20sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text=":"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/contact_list_name_item"
                android:layout_width="190dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="Name"
                android:textColor="#FFFF00"
                android:textSize="20sp" />

        </LinearLayout>


        <LinearLayout
            android:id="@+id/contact_layout_number"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="35dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="5dp"
                android:text="Number"
                android:textAlignment="center"
                android:textColor="#E6E6E6"
                android:textSize="20sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="5dp"
                android:text=":"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/contact_list_number_item"
                android:layout_width="190dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="5dp"
                android:text="Number"
                android:textColor="#FFFF00"
                android:textSize="20sp" />

        </LinearLayout>


        <LinearLayout
            android:id="@+id/contact_layout_relation"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="60dp"
            android:layout_marginBottom="15dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="10dp"
                android:text="Relationship"
                android:textAlignment="center"
                android:textColor="#E6E6E6"
                android:textSize="20sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:text=":"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/contact_list_relation_item"
                android:layout_width="190dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:text="Relationship"
                android:textColor="#FFFF00"
                android:textSize="20sp" />

        </LinearLayout>

    </androidx.cardview.widget.CardView>

</androidx.cardview.widget.CardView>

我没有通读并理解您的所有代码,但我觉得这些行不对:

holder.contact_name.setText(helper.getContactName(c));
holder.contact_number.setText(helper.getContactNumber(c));
holder.contact_relation.setText(helper.getContactRelation(c));

也许可以尝试使用 position

你在调试你的代码吗?方法呢

 public void swapCursor(Cursor newCursor){
        if (c != null){
            c.close();
        }

        c = newCursor;

        if (newCursor != null){
            notifyDataSetChanged();
        }
    }

notifyDataSetChanged() 是您应该调用的方法。

尝试将所有项目复制到arrayList(仅用于测试),然后在onBindViewHolder中按位置获取项目

我在想你的问题 - c.moveToFirst();在 onBindViewHolder

您的代码中存在一些问题。 我将从在 recyclerview 回收视图时保持打开状态的 Cursor 开始。这不好,而且,您在 UI 线程中执行此操作,这会大大降低您的 UI 速度。

我建议您阅读所有数据并将其传递给您的适配器。这就是适配器的用途:它们是访问数据的一种方式,但它们不必知道有关如何访问数据的任何信息。所以第一件事是改变数据库助手,添加一个循环遍历数据库中所有数据的方法和returns一个列表:

public List<Contact> readAllContacts() {
    List<Contact> contacts = new ArrayList();
    Cursor cursor = this.getContactDatabase();
    if (cursor.moveToFirst()){
       do {
          contacts.add(new Contact(cursor.getString(0), cursor.getString(1), cursor.getString(2)));
       } while(cursor.moveToNext());
    }
    cursor.close();
}

您还需要使用 public 构造函数创建联系人 class。

然后,我将修改适配器,以接收联系人列表,而不是光标:

public ContactAdapter(Context context,List<Contact> contacts) {
    mContext = context;
    this.contacts = contacts;
}

您将不再需要适配器中的 db 助手,因为您已经拥有整个列表并且游标现在已经关闭,从而提高了整个 UI 的性能。此外,您还需要一个名为 contacts 的 class 属性,类型为 List。

现在您可以按位置访问单行的值,因此在您的 onBindViewHolder 中您将拥有:

public void onBindViewHolder(MyHolder holder, final int position) {
    holder.contact_name.setText(this.contacts.get(position).getName());
    holder.contact_number.setText(this.contacts.get(position).getNumber());
    holder.contact_relation.setText(this.contacts.get(position).getContactRelation());

}

这已经可以工作了。最重要的是,我热烈建议您开始使用 Room 而不是编写自己的数据库助手。