【问题标题】:How can I make list changes animations while using custom way of saving data RecyclerView如何在使用自定义方式保存数据 RecyclerView 时制作列表更改动画
【发布时间】:2019-11-01 11:04:51
【问题描述】:

我正在制作一个备忘录应用程序,它使用 RecyclerView 来显示 ArrayList<Note> 的数据,其中 Note 是每个项目的数据类,我使用另一个名为 NotesController 的类(使用 Gson)保存和检索它们。为了更新列表,我现在要做的是为我设置到列表中的 NotesAdapter(RecyclerView 适配器)重新分配一个新值。这是我的代码:

NotesController:

public class NotesController {

    private ArrayList<Note> notesList;
    private String notesPath;

    private Gson gson = new Gson();
    private Type type = new TypeToken<ArrayList<Note>>() {
    }.getType();

    public NotesController(String notesPath) {
        this.notesPath = notesPath;
        if (FileUtil.isExistFile(notesPath)) {
            getNotesList();
        } else {
            createNewList();
        }
    }

    /**
     * Creates a new list if it doesn't exist. Internal class use only.
     */
    private void createNewList() {
        notesList = new ArrayList<>();
        saveLatestData();
    }

    /**
     * Reads the saved notes.json file and retrieves the ArrayList of items of class {@link Note}.
     * @return An ArrayList<<h>Note</h>> containing all notes saved in file <b>notes.json</b>
     */
    public ArrayList<Note> getNotesList() {
        String json = FileUtil.readFile(notesPath);
        notesList = gson.fromJson(json, type);
        return notesList;
    }

    /**
     * Saves latest changes to the list {@linkplain NotesController#notesList} to notes.json file. Internal class use only.
     */
    private void saveLatestData() {
        String json = gson.toJson(notesList, type);
        FileUtil.writeFile(notesPath, json);
    }

    /**
     * Adds an item of type {@link Note} to the list and saves data by calling {@link NotesController#saveLatestData()}.
     * @param note The {@link Note} instance to get added.
     */
    public void add(Note note) {
        notesList.add(0, note);
        saveLatestData();
    }

    /**
     * Replaces an existing item with a new one of type {@link Note} in the list {@link NotesController#notesList} and saves data by calling {@link NotesController#saveLatestData()}.
     * @param position The position of the item to get replaced.
     * @param note The {@link Note} instance to replace the old item.
     * @throws ArrayIndexOutOfBoundsException When position is out of {@link NotesController#notesList} range.
     */
    public void set(int position, Note note) {
        notesList.set(position, note);
        saveLatestData();
    }

    /**
     * Gets the {@link Note} item from the specified position.
     * @param position The position of the item to return.
     * @return The item at the position specified.
     * @throws ArrayIndexOutOfBoundsException When position is out of {@link NotesController#notesList} range.
     */
    public Note get(int position) {
        return notesList.get(position);
    }

    /**
     * Removes the {@link Note} item in the specified position from the list.
     * @param position The position of the item to remove.
     * @throws ArrayIndexOutOfBoundsException When position is out of {@link NotesController#notesList} range.
     */
    public void remove(int position) {
        notesList.remove(position);
        saveLatestData();
    }

    /**
     * Indexes the notes list for the given text and returns items that contain the query either in the title or the content.
     * @param query The text query to search for (low cased).
     * @return The notes whose title or content contains the query (all trimmed and low cased).
     */
    public ArrayList<Note> search(String query) {
        ArrayList<Note> results = new ArrayList<>();
        for (Note note: getNotesList()) {
            if (note.getTitle().trim().toLowerCase().contains(query.trim().toLowerCase()) || note.getContent().trim().toLowerCase().contains(query.trim().toLowerCase())) {
                results.add(note);
            }
        }
        return results;
    }

    /**
     * Simple method to convert many int parameters to an int[] array.
     * @param categories The varargs int[] array.
     * @return int[] array from parameters.
     */
    public int[] categories(int... categories) {
        return categories;
    }
}

MainActivity: (只是相关代码)

public class MainActivity extends AppCompatActivity {

    private NotesAdapter notesAdapter;
    public static NotesController notesController;
    private RecyclerView notesRecyclerView;
    private String notesDir;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Fabric.with(this, new Answers(), new Crashlytics());
        setContentView(R.layout.activity_main);

        ...

        notesDir = ContextCompat.getDataDir(this).getPath() + "/files/notes.json";
        notesController = new NotesController(notesDir);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        notesRecyclerView.setLayoutManager(layoutManager);
        updateRecyclerView();

        notesAdapter.setOnItemActionListener(new NotesAdapter.ActionListener() {
            @Override
            public void onItemClick(final int position, View v) {
                ...
            }

            @Override
            public void onItemLongClick(final int position, View v) {
                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this).setTitle("Delete?").setMessage("Just for testing.");
                dialog.setPositiveButton("DELETE", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        notesController.remove(position);
                        updateRecyclerView();
                    }
                });
                dialog.show();
            }
        });

        ...
    }

    ...

    private void updateRecyclerView() {
        notesAdapter = new NotesAdapter(notesController.getNotesList(), getApplicationContext());
        notesRecyclerView.setAdapter(notesAdapter);
        notesAdapter.notifyDataSetChanged();
    }

}

现在查看updateRecyclerView() 方法,您会看到我再次使用来自 NotesController 的新数据重新分配适配器,然后通知列表数据已更改。

但是我需要在不消除控制器的情况下以某种方式在我删除(例如通过长按)或添加某些内容(只是默认的)时使列表制作删除动画。为此,Android RecyclerView Adapter 类为我们提供了notifyItemInserted(int)notifyItemRemoved(int),但在我的情况下它们不起作用(即使删除了中断这些动画的 notifyDataSetChanged())。

请不要建议我删除 NotesController,因为它有助于轻松访问应用程序不同部分的笔记,我只需要一种方法让这两种插入和删除通知方法正常工作(欢迎任何其他解决方案顺便说一句)。

注意:这是我的适配器类型:public class NotesAdapter extends RecyclerView.Adapter&lt;NotesAdapter.NoteViewHolder&gt;

【问题讨论】:

    标签: java android list android-recyclerview android-animation


    【解决方案1】:

    当您想更新 recyclerview 中的项目时,您不应该创建新的适配器实例。您应该创建一个适配器实例并将其分配给recyclerview,如果您想在recyclerview中添加或删除项目,您只需要替换适配器中的数据。我会推荐ListAdapter,因为它具有submitList(list) 功能,可以很容易地用于更新数据。

    另外如果你想实现动画你可以使用this

    【讨论】:

    • 谢谢兄弟,我去看看!
    • public class NotesAdapter extends RecyclerView.Adapter&lt;NotesAdapter.NoteViewHolder&gt; 没有任何名为 submitList(list); 的函数。有没有其他选择?还是我应该创造这样的东西?
    • 阅读本文以供参考。它使用我提到的ListAdapterhmkcode.com/android/android-recyclerview-listadapter
    • 非常感谢您的帮助,但我通过将我自己的 submitData() 函数放入适配器和动画自动工作(使用 notifyItemRemoved/Added())解决了这个问题!
    【解决方案2】:

    我通过使用 - 如 Milan Kundacina 所建议的 - 函数 submitList(list) 而不是重新分配适配器来解决问题。但由于此功能仅与 ListAdapter 一起使用,而我只使用 Adapter,我创建了自己的一个,如下所示(suuuuuper 简单):

    public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NoteViewHolder> {
    
        private ArrayList<Note> notesList;
    
        ...
    
        NotesAdapter(ArrayList<Note> notesList) {
            super();
            this.notesList = notesList;
        }
    
        public void submitList(ArrayList<Note> list) {
            this.notesList = list;
        }
    
        ...
    
    }
    

    并用这种方式更新列表:

    // inside MainActivity:
    
    private void notifyListAdd(int position) {
        notesAdapter.submitList(notesController.getNotesList());
        notesAdapter.notifyItemInserted(position);
    }
    
    private void notifyListRemove(int position) {
        notesAdapter.submitList(notesController.getNotesList());
        notesAdapter.notifyItemRemoved(position);
    }    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      • 2017-02-23
      • 1970-01-01
      相关资源
      最近更新 更多