【问题标题】:RecyclerView doesn't inflate, rather updates the same view?RecyclerView 不会膨胀,而是更新相同的视图?
【发布时间】:2018-06-08 12:08:09
【问题描述】:

我有一个活动来实现一个待办事项列表,其中包含一个 recyclerview,每个项目都是一个复选框和 textview,每个任务都是从一个 edittext 添加的。 它使用 Realm.io 存储数据。我不断得到的行为是 recyclerview 中的单个元素只是得到更新,而不是膨胀!请帮忙。

TasksActivity -

public class TasksActivity extends AppCompatActivity implements View.OnClickListener{

    TextView courseTitle;
    RecyclerView TaskList;
    EditText addTask;
    Button addButton;

    String transName; //Transferred Course name from MainActivity


    TaskAdapter TA;

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

        courseTitle = findViewById(R.id.CourseName);
        TaskList = findViewById(R.id.TaskListRV);
        TaskList.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));


        addTask = findViewById(R.id.InputTask);
        addButton = findViewById(R.id.AddTaskButton);

        //Course name is the obtained from the previous acivity.

        transName =getIntent().getExtras().getString("CourseName");
        courseTitle.setText(transName);

        TA = new TaskAdapter(transName);
        TaskList.setAdapter(TA);

        addButton.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {

        String task = addTask.getText().toString();

        // Checking if the text is empty.

        boolean flag = false;
        for(int i = 0;i<task.length();i++)
        {
            if(task.charAt(i)!=' ')
                flag = true;
        }

        if(!flag || task.equals(""))
        {
            Toast emptyWarning = Toast.makeText(getApplicationContext(),"Task cannot be Empty!",Toast.LENGTH_SHORT);
            emptyWarning.show();
        }
        else
        {
            addTask.setText("");
            TA.addNewTask(task);

        }
    }

}

TasksAdapter -

public class TaskAdapter extends RecyclerView.Adapter<TaskViewHolder> implements RealmChangeListener<RealmResults<TaskModel>>
{

    private ArrayList<TaskModel> TaskList;
    private String course;
    private final Realm realm;



        public TaskAdapter(String course)
        {
            this.course = course;

            this.TaskList = new ArrayList<>();
            realm = Realm.getDefaultInstance();
            loadTaskData();
        }

        void loadTaskData()
        {
            RealmResults<TaskModel> taskModelRealmResults = realm.where(TaskModel.class).equalTo("courseName",course).findAll();
            taskModelRealmResults.addChangeListener(this);

            for(TaskModel iTM : taskModelRealmResults)
            {
                TaskList.add(realm.copyFromRealm(iTM));
            }
            notifyDataSetChanged();

        }

        @Override
        public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
            View view= layoutInflater.inflate(R.layout.item_task,parent,false);

            TaskViewHolder Tvh = new TaskViewHolder(view);
            return Tvh;
        }

        @Override
        public void onBindViewHolder(TaskViewHolder holder, int position) {
            holder.populateTask(TaskList.get(position));

        }

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

        public void addNewTask(String task)
        {
            TaskModel newTaskObj = new TaskModel(task,course,false);

            TaskList.add(newTaskObj);
            notifyDataSetChanged();

            realm.beginTransaction();
            realm.insertOrUpdate(newTaskObj);
            realm.commitTransaction();

        }


        @Override
        public void onChange(RealmResults<TaskModel> taskModels) {

            taskModels = realm.where(TaskModel.class).equalTo("courseName",course).findAll();
            this.TaskList = new ArrayList<>();

            for(TaskModel iTM : taskModels)
            {
                this.TaskList.add(realm.copyFromRealm(iTM));
            }
            notifyDataSetChanged();
        }

    }

TaskViewHolder 和 TaskModel -(如果你可能需要它们)

public class TaskModel extends RealmObject {

    String task;

    @PrimaryKey
    String courseName;

    boolean isDone;

    public TaskModel() {
        task = "";
        courseName = "";
        isDone = false;
    }

    public TaskModel(String task, String courseName, boolean isDone) {
        this.task = task;
        this.courseName = courseName;
        this.isDone = isDone;
    }


    public String getTask() {
        return task;
    }

    public void setTask(String task) {
        this.task = task;
    }

    public boolean isDone() {
        return isDone;
    }

    public void setDone(boolean done) {
        isDone = done;
    }
}

public class TaskViewHolder extends RecyclerView.ViewHolder  {

    CheckBox isdone;
    TextView Taskname;


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

        isdone = itemView.findViewById(R.id.TaskCheckBox);
        Taskname = itemView.findViewById(R.id.TaskName);

    }

    void populateTask(final TaskModel T)
    {
        Taskname.setText(T.getTask());
        isdone.setChecked(T.isDone());

        isdone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                T.setDone(isdone.isChecked());
            }
        });
    }

}

【问题讨论】:

  • merely get updated, and not inflated! 不是RecyclerView 的工作原理吗?重复使用视图而不是创建新视图?
  • 我的意思是 update 因为在同一组视图中被下一组数据替换。一次只显示一个单个视图
  • 这可能是因为该视图的布局足够大,可以覆盖整个 RecyclerView。
  • onChange 是否返回整个列表?还是只是最后一项已更改?
  • private ArrayList&lt;TaskModel&gt; TaskList;TaskList.add(realm.copyFromRealm(iTM)); 为什么???什么例子说明了这一点?因为我知道officials don't

标签: java android realm android-recyclerview


【解决方案1】:

我建议您使用Realm Android dapter,此适配器负责更新您的应用程序 UI。不需要实现 OnChangeListener,你的列表会在插入、删除或编辑后自动更新

使用findAllAsync 以免阻塞 UI 线程

OrderedRealmCollection<TaskModel> taskModels = realm.where(TaskModel.class).equalTo("courseName", course).findAllAsync();

public RealmAdapter(OrderedRealmCollection<TaskModel> data) {
    super(data, true);
}

编辑:

如果可能,请始终使用 Async 方法执行该过程。您可以通过以下方式替换您的 addNewTask 方法:

public void addNewTask(String task) {
     final TaskModel newTaskObj = new TaskModel(task, course, false);

     realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm.copyToRealmOrUpdate(newTaskObj);
        }
     });
}

你应该有这样的东西:

TasksActivity

public class TasksActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText addTask;

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

        String transName = getIntent().getExtras().getString("CourseName");

        TextView courseTitle = findViewById(R.id.CourseName);
        courseTitle.setText(transName);

        addTask = findViewById(R.id.InputTask);

        findViewById(R.id.AddTaskButton).setOnClickListener(this);

        OrderedRealmCollection<TaskModel> taskModels = Realm.getDefaultInstance().where(TaskModel.class).equalTo("courseName", transName).findAllAsync()
        TaskAdapter adapter = new TaskAdapter(this, taskModels);

        RecyclerView taskList = findViewById(R.id.TaskListRV);
        taskList.setLayoutManager(new LinearLayoutManager(this));
        taskList.setAdapter(adapter);
    }

    @Override
    public void onClick(View view) {

        String task = addTask.getText().toString().trim();

        if (task.trim().isEmpty()) {
            Toast emptyWarning = Toast.makeText(getApplicationContext(),"Task cannot be Empty!",Toast.LENGTH_SHORT);
            emptyWarning.show();
            return;
        }

        addTask.setText("");
        addNewTask(task);
    }

    private void addNewTask(String task) {
        final TaskModel newTaskObj = new TaskModel(task, course, false);
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealmOrUpdate(newTaskObj);
            }
        });
    }
}

还有TaskAdapter

public class TaskAdapter extends RealmRecyclerViewAdapter<TaskModel, TaskViewHolder> {

    private LayoutInflater layoutInflater

    public TaskAdapter(Context context, OrderedRealmCollection<TaskModel> taskModels) {
        super(taskModels, true);

        this.layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new TaskViewHolder(layoutInflater.inflate(R.layout.item_task , parent, false));
    }

    @Override
    public void onBindViewHolder(TaskViewHolder holder, int position) {
        holder.populateTask(getItem(position));
    }
}

【讨论】:

  • 你如何使用这个适配器?我正在使用 Realm 5.3.0(最新),但此适配器不存在。我必须添加另一个依赖项吗?
  • 只需要添加这个依赖:implementation 'io.realm:android-adapters:2.1.1'
  • 适配器有一个新版本,3.0.0 => implementation 'io.realm:android-adapters:3.0.0'
  • 感谢您提供急需的帮助。我得到了膨胀视图所需的行为,但是当我再次打开 TasksActivity 时数据消失了。 copyToRealmOrUpdate 应该可以正常工作吗?
  • copyToRealmOrUpdate 应该更新或创建对象,它不会删除您的数据库。您确定不在其他地方清除您的领域数据库吗?
【解决方案2】:

在这里。我最终使用了标准的ReacyclerView.Adapter。 问题在于 Realm 的 insertOrUpdate 方法的使用,当 @PrimaryKeycourseName 时,这导致它确实更新了同一个对象而不是创建一个新对象! 应该使用insert()。 这里是插入任务方法——

  public void addNewTask(String task)
{
    boolean flag = false;

    for(int i = 0;i<TaskList.size();i++)
    {
        if(task.equals(TaskList.get(i).getTask()))
        {
            Toast.makeText(context,"Task already exists!",Toast.LENGTH_SHORT).show();
            flag = true;
            break;
        }
    }
    if(!flag)
    {
        TaskModel newTaskObj = new TaskModel();
        newTaskObj.setTask(task);
        newTaskObj.setDone(false);
        newTaskObj.setCourseName(course);

        TaskList.add(newTaskObj);
        notifyDataSetChanged();

        realm.beginTransaction();
        realm.insert(newTaskObj);
        realm.commitTransaction();
    } }

整个项目都可以在这里找到,请检查一下 - https://github.com/Hariram-R/ToDoList-App

【讨论】:

    猜你喜欢
    • 2022-09-30
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多