在 recyclerView 的 itemclick 上

On itemclick of recyclerView

我试图制作一个应用程序,在其中制作了项目数组列表的回收视图,我希望当我单击数组列表的特定项目时,它应该打开一个 activity,我在其中如果我想打开 Array List 的另一个项目,可以添加一些带有编辑文本的文本,所以它应该打开相同的 activity 但不是以前保存的数据。

我想在每个项目列表中添加不同的数据。但它不会发生在每个项目列表中,相同的保存数据正在加载 activity...

有什么解决办法吗..

这是第二个activity..

 protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.student_list);

    loadData();

    toolbar = findViewById(R.id.toolbar);

    bundle = getIntent().getExtras();
    String subName = bundle.getString("Subject Name");

    if (bundle != null) {
        toolbar.setTitle(subName);
    }

    fabButton();
    buildRecyclerView();
}

private void buildRecyclerView() {

    recyclerView = findViewById(R.id.recyclerView2);
    recyclerView.hasFixedSize();
    layoutManager = new LinearLayoutManager(StudentListActivity.this);
    rAdapter = new AdapterForStudentList(listOfNames);

    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(rAdapter);

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView);

}

public void insertData(String text, String t1, String t2) {
    ListOfNames lt = new ListOfNames(text, t1, t2);
    listOfNames.add(lt);
    rAdapter.notifyDataSetChanged();

}

public void saveData() {
    sharedPreferences = getSharedPreferences("SHARED PREF", MODE_PRIVATE);
    editor = sharedPreferences.edit();

    Gson gson = new Gson();
    String json = gson.toJson(listOfNames);

    editor.putString("text", json);
    editor.apply();
}

public void loadData() {


    sharedPreferences = getSharedPreferences("SHARED PREF", MODE_PRIVATE);

    Gson gson = new Gson();
    String json = sharedPreferences.getString("text", null);
    Type type = new TypeToken<ArrayList<ListOfNames>>() {
    }.getType();

    listOfNames = gson.fromJson(json, type);

    if (listOfNames == null) {
        listOfNames = new ArrayList<>();
    }
}

ListOfNames deletedItem = null;
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        final int position = viewHolder.getAdapterPosition();
        String name = listOfNames.get(position).getStudentName();

        deletedItem = listOfNames.get(position);
        listOfNames.remove(deletedItem);

        sharedPreferences = getSharedPreferences("SHARED PREF", MODE_PRIVATE);
        editor = sharedPreferences.edit();
        editor.remove("text");


        saveData();
        editor.apply();
        rAdapter.notifyItemRemoved(position);

        Snackbar.make(recyclerView, name + "Deleted", Snackbar.LENGTH_LONG)
                .setAction("Undo", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        listOfNames.add(position, deletedItem);
                        rAdapter.notifyItemInserted(position);

                        saveData();
                    }
                }).show();
    }

    @Override
    public void onChildDrawOver(@NonNull Canvas c, @NonNull RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        new RecyclerViewSwipeDecorator.Builder(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)

                .addSwipeLeftBackgroundColor(ContextCompat.getColor(StudentListActivity.this, R.color.my_background))
                .addSwipeLeftActionIcon(R.drawable.ic_delete_black_24dp)
                .create()
                .decorate();
        super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

    }
};

public void fabButton() {
    FloatingActionButton floatingActionButton = findViewById(R.id.fab2);
    floatingActionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AlertDialog.Builder b = new AlertDialog.Builder(StudentListActivity.this);
            View view = getLayoutInflater().inflate(R.layout.dialogbox_frontpage, null);

            final EditText editText = view.findViewById(R.id.editText);
            b.setView(view);
            b.setTitle("Student name");
            b.setPositiveButton("ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String text = editText.getText().toString();

                    if (text.isEmpty()) {
                        Toast.makeText(StudentListActivity.this, "Please add subject name", Toast.LENGTH_SHORT).show();
                    } else {
                        insertData(text, t1, t2);
                        saveData();
                    }
                }
            });
            b.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
            b.setCancelable(false);
            b.show();
        }
    });
}

}

**MainActivity**

`public class ScrollingActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private AdaptreForRecycler adapter;
private RecyclerView.LayoutManager layoutManager;
private ArrayList<ExampleItem> mExampleList;
RecyclerView.ViewHolder viewHolder;


private Gson gson;
private String json;
private Type type;

private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;


EditText editText;
private ExampleItem ex;
public static final String t2 = "new";



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


    loadData();
    buildRecyclerView();

    editText = findViewById(R.id.editText);
    fabButoonClick();


}

public void saveData() {

    sharedPreferences = getSharedPreferences("SHARED_PREFS", MODE_PRIVATE);
    editor = sharedPreferences.edit();
    gson = new Gson();
    json = gson.toJson(mExampleList);

    editor.putString("text", json);
    editor.apply();

}

public void loadData() {

    sharedPreferences = getSharedPreferences("SHARED_PREFS", MODE_PRIVATE);
    gson = new Gson();
    json = sharedPreferences.getString("text", null);
    type = new TypeToken<ArrayList<ExampleItem>>() {
    }.getType();
    mExampleList = gson.fromJson(json, type);

    if (mExampleList == null) {
        mExampleList = new ArrayList<>();
    }

}


public void insertItem(String text, String t2) {

    ex = new ExampleItem(text, t2);
    mExampleList.add(ex);
    adapter.notifyDataSetChanged();


}

ExampleItem deletedIndex = null;
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        final int position = viewHolder.getAdapterPosition();
        String name = mExampleList.get(position).getText1();
        deletedIndex = (mExampleList.get(position));
        mExampleList.remove(position);

        sharedPreferences = getSharedPreferences("SHARED_PREFS", MODE_PRIVATE);
        editor = sharedPreferences.edit();
        editor.remove("text");

        saveData();

        editor.apply();
        adapter.notifyItemRemoved(position);

        Snackbar.make(recyclerView, name + " Deleted", Snackbar.LENGTH_LONG)
                .setAction("Undo", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mExampleList.add(position, deletedIndex);
                        adapter.notifyItemInserted(position);

                        saveData();

                    }
                }).show();
    }

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {

        new RecyclerViewSwipeDecorator.Builder(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)

                .addSwipeLeftBackgroundColor(ContextCompat.getColor(ScrollingActivity.this, R.color.my_background))
                .addSwipeLeftActionIcon(R.drawable.ic_delete_black_24dp)
                .create()
                .decorate();
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
};


private void buildRecyclerView() {
    recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    layoutManager = new LinearLayoutManager(ScrollingActivity.this);
    adapter = new AdaptreForRecycler(mExampleList);

    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);

    adapter.setOnItemClickListener(new AdaptreForRecycler.OnItemCLickListener() {
        @Override
        public void onItemClick(int position) {


            Intent i =new Intent(ScrollingActivity.this,StudentListActivity.class);
            i.putExtra("Subject Name",mExampleList.get(position).getText1());

            startActivity(i);
        }
    });

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView);
}

public void fabButoonClick() {
    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            AlertDialog.Builder b = new AlertDialog.Builder(ScrollingActivity.this);
            View mview = getLayoutInflater().inflate(R.layout.dialogbox_frontpage, null);

            final EditText editText = mview.findViewById(R.id.editText);
            b.setView(mview);
            b.setTitle("Add subject name");
            b.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });

            b.setPositiveButton("ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String text = editText.getText().toString();

                    if (text.isEmpty()) {
                        Toast.makeText(ScrollingActivity.this, "Please add subject name", Toast.LENGTH_SHORT).show();
                    } else {

                        insertItem(text, t2);

                        saveData();
                    }
                }
            });
            b.setCancelable(false);
            b.show();
        }
    });

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.menu_scrolling, menu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();


    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}</code>AdaptreOfFirstActivity`</p> <pre><code>public class AdaptreForRecycler extends RecyclerView.Adapter<AdaptreForRecycler.ProgrammingViewHolder> { private OnItemCLickListener mListener; public interface OnItemCLickListener { void onItemClick(int position); } public void setOnItemClickListener(OnItemCLickListener listener) { mListener = listener; } private ArrayList<ExampleItem> mExampleList; public class ProgrammingViewHolder extends RecyclerView.ViewHolder { public TextView mTextView1, mTextView2; public ProgrammingViewHolder(@NonNull View itemView, final OnItemCLickListener listener) { super(itemView); mTextView1 = itemView.findViewById(R.id.tv1); mTextView2 = itemView.findViewById(R.id.tv2); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listener != null) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) listener.onItemClick(position); } } }); } } public AdaptreForRecycler(ArrayList<ExampleItem> exampleList) { mExampleList = exampleList; } @NonNull @Override public AdaptreForRecycler.ProgrammingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View view = inflater.inflate(R.layout.list_item_layout, parent, false); return new ProgrammingViewHolder(view, mListener); } @Override public void onBindViewHolder(@NonNull AdaptreForRecycler.ProgrammingViewHolder holder, int position) { ExampleItem currentItem = mExampleList.get(position); holder.mTextView1.setText(currentItem.getText1()); holder.mTextView2.setText(currentItem.getText2()); } @Override public int getItemCount() { return mExampleList.size(); }

} AdaptreForSecondActivity

public class AdapterForStudentList extends RecyclerView.Adapter<AdapterForStudentList.StudentViewHolder> {


private ArrayList<ListOfNames> mListOfNames;

public static class StudentViewHolder extends RecyclerView.ViewHolder {
    public TextView studentName, attendence, percentage;

    public StudentViewHolder(@NonNull View itemView) {
        super(itemView);
        studentName = itemView.findViewById(R.id.studentName);
        attendence = itemView.findViewById(R.id.attendence);
        percentage = itemView.findViewById(R.id.percentage);


    }
}

public AdapterForStudentList(ArrayList<ListOfNames> listOfNames) {

    mListOfNames = listOfNames;
}

@NonNull
@Override
public StudentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.check_box_cardview, parent, false);

    return new StudentViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull StudentViewHolder holder, int position) {

    ListOfNames currentItems = mListOfNames.get(position);
    holder.studentName.setText(currentItems.getStudentName());
    holder.attendence.setText(currentItems.getAttendent());
    holder.percentage.setText(currentItems.getPercetage());
}

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

}

现在我看到你做到了我在第一个原始答案中所说的,我为你点赞。

此外,这个 thread/post 可以在这里结束,因为您已经为 RecyclerView 实现了 onClick。如果您将我的回答标记为解决方案,我将不胜感激。

当然,您提出了另一个问题,即:

I want to add different data in each list of items. but its not happening for every list of items the same saved data is loading in the activity...

那是因为您正在使用 相同的密钥进行加载和保存:

editor.putString("text", json);
editor.apply();

看到了吗?您正在加载并保存到每个主题中的键 "text"。 (你提到你有一个主题列表,因此我使用了 subject 这个词)

我建议您创建一种方法来更改每个不同主题的密钥。在这种情况下,您的主题名称可以是键,而不是普通的 "text".

我还建议您为 "text" 使用 private static final String 变量,并使其更清晰。一个叫做 "text" 的键有点模棱两可你不觉得吗?

现在我将 post 您 StudentListActivity 的修改代码部分,我鼓励您对其进行分析并将其粘贴到您的代码中。我相信它现在会起作用。

StudentListActivity中的修改部分

// Added a string variable here as key for saving/loading your data
String subName; // I kept your naming the same which is 'subName'

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.student_list);

    // I placed this bit of code above loadData() now that we
    // use subName as the key
    // Or else loadData() will use the initial value of
    // subName which is going to be null first
    bundle = getIntent().getExtras();
    subName = bundle.getString("Subject Name");

    if (bundle != null) {
        toolbar.setTitle(subName);setTitle(subName);
    }

    loadData();

    toolbar = findViewById(R.id.toolbar);

    fabButton();
    buildRecyclerView();
}

// Other code... Which in your code are:
// private void buildRecyclerView() { ... }
// public void insertData(String text, String t1, String t2) { ... }

public void saveData() {
    sharedPreferences = getSharedPreferences("SHARED PREF", MODE_PRIVATE);
    editor = sharedPreferences.edit();

    Gson gson = new Gson();
    String json = gson.toJson(listOfNames);

    // Now here use the name of your subject as key
    // Which is of course the variable 'subName'
    editor.putString(subName, json);
    editor.apply();
}

public void loadData() {


    sharedPreferences = getSharedPreferences("SHARED PREF", MODE_PRIVATE);

    Gson gson = new Gson();
    // Same here
    // Use 'subName' as key
    String json = sharedPreferences.getString(subName, null);
    Type type = new TypeToken<ArrayList<ListOfNames>>() {
    }.getType();

    listOfNames = gson.fromJson(json, type);

    if (listOfNames == null) {
        listOfNames = new ArrayList<>();
    }
}

// Other code ...

顺便说一句,我尝试自己制作布局以测试您的应用程序,我注意到了一些事情:我猜您的 dialogbox_frontpage.xml 文件中有一个 EditText .而且您仍然编写了一段代码来获取 ScrollingActivity 的视图,这是不必要的。事实上,你 re-defined 它在 fab 的 onClick 方法中。您可以删除该 global 变量。

最后说明:这只是一个建议,但您可以尝试了解 Singleton 模式。使用该模式来保存您的数据。 此外,SharedPreferences 并不是保存大量数据的好主意。因此,我也鼓励您尝试查找 Room 数据库。

希望您的程序一如既往地正常运行,编码愉快! (这个回答很长,哈哈哈)


原回答(稍作修改)

我建议创建一个 interface 来传递被点击项目的位置,因为我们只关心项目的位置以便能够对它做一些事情。此外,这样更好,这样我们就可以在 activity 中放入单击某个项目时要执行的代码。

interface 应该是这样的:

public interface OnItemClickListener {
    void onItemClick(int position);
}

在你的adapter里面添加一个新的variable,也就是OnItemClickListener:

private OnItemCLickListener listener;

您可以通过将其实现到 activity 来定义它的实现,或者通过创建另一个名为 addOnItemClickListener 的方法将其实现传递到您的 adapter:

addOnItemClickListener(OnItemClickListener listener) {
    this.listener = listener;
}

然后在你的 onBindViewHolder 方法中,从 ViewHolder 中获取项目的布局并设置它的 onClick 侦听器,最后在它的 onClick 方法中,调用你的接口的方法 onItemClick 在其中并将位置传递到那里。像这样:

@Override
public void onBindViewHolder(@NonNull CustomRecyclerView.ViewHolder holder, final int position) {
    holder.layout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            listener.onItemClick(position);
        }
    });
}



编辑:解释为什么我在 onBindViewHolder 方法中设置侦听器

我们从 ViewHolder 的构造函数中得到的 itemViewView 取决于 返回的 View onCreateViewHolder 中的 LayoutInflater。因此,您在 inflate 方法中传递的布局资源,无论您在那里使用的主要布局是什么(例如 ConstraintLayoutLinearLayout,它也可以是 TextView, Button, 等), 将返回 View。要对此进行测试,请在您的 onCreateViewHolder 中尝试 copy/paste 这行简单的代码,然后 运行 您的应用并检查 Logcat:

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(context).inflate(R.layout.YOUR_LAYOUT_HERE, parent, false);
    Log.i("View", view.getClass().getSimpleName()); // Logs the main view in our layout
    return new YourCustomViewHolderHere(view);
}

ViewHolder 负责获取我们的视图,因为如果我们在 [=39= 中使用 findViewById 方法是一项广泛的任务] 所以我们不在那里这样做,因为它会降低我们应用程序的性能。

我们进行所有设置,例如更改 TextViews 的文本或设置 onClick 听众 inside onBindViewHolder 以避免创建我们的代码中不必要的复杂性。我们现在不希望代码四处飘荡,对吗?

此外,观察者模式非常危险

在一个 Android 会议上有一个演讲,我不记得是哪个,讲的是 RecyclerView。你知道为什么这样叫吗?因为它 回收 视图。 (它需要一个适当的解释他们如何回收视图,所以我不会在这里覆盖它。我想你可以在 YouTube 上找到它,如果你搜索 "Android Conference RecyclerView",它相当很长,大概一个小时左右,但值得一看。)

观察者模式(即监听器)可能会导致内存泄漏,从而影响我们应用程序的性能。因此,最好在我们的 onBindViewHolder 方法中设置它,因为每当我们在 RecyclerView 上向下或向上滚动时,它都会回收视图,而我们 riskViewHolder.

中创建 多个 same 侦听器实例

根据 Observer pattern 上的维基百科:

The observer pattern can cause memory leaks, known as the lapsed listener problem, because in basic implementation it requires both explicit registration and explicit deregistration, as in the dispose pattern, because the subject holds strong references to the observers, keeping them alive. This can be prevented by the subject holding weak references to the observers.

另一种设置 onClick 的方法是在 onCreateViewHolder 中,但要注意的是你无法知道哪个项目 w点击了。

我希望这能回答您在评论中提出的问题。