pdate:問題の1つが解決されました:updateList
が解決され、mAdapter
をMyAdapter
ではなくRecyclerView.Adapter
として定義したことが問題でした。しかし、今はデータを取得していますが、リストには何も表示されず、空です
--------------------元の投稿 --------------------
重複を防ぐためにRecyclerView
を使用してDiffUtil
を更新したい。
4つのクラスがあります。Userクラス、データを設定するActivity
クラス、Adapter
クラス、およびDiffUtil
クラスです。これら4つすべてを正しく組み合わせているかどうかはわかりません。
これはUserクラスです:
public class User {
private String mUserId;
private Uri mImageUrl;
public User(String userId, String imageUrl) {
mUserId = userId;
mImageUrl = Uri.parse(imageUrl);
}
public String getUserId() {
return mUserId;
}
public Uri getImageUrl() {
return mImageUrl;
}
}
これは、データを動的に設定する方法です(表示するユーザーIDを含むサーバーから新しいJson
配列を取得し続け、次にFirebase
ストレージからユーザーイメージを設定します):(これは呼び出された関数ですonClickリスナーによる:)
これはフラグメントからのメソッド呼び出しです:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
updateUsersList();
}
});
これは関数です:
private void updateUsersList() {
@Override
public void onResponse(JSONArray response) { // the JSON ARRAY response of user ids ["uid1", "uid334", "uid1123"]
myDataset.clear(); // clear dataset to prevent duplicates
for (int i = 0; i < response.length(); i++) {
try {
String userKey = response.get(i).toString(); // the currently iterated user id
final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userKeyRef = rootRef.child("users").child(userKey); // reference to currently iterated user
ValueEventListener listener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
myDataset.add(new User(dataSnapshot.getKey(), dataSnapshot.child("imageUrl").getValue().toString())); //add new user: id and image url
mAdapter.updateList(myDataset); // cannot resolve this method, why?
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
userKeyRef.addListenerForSingleValueEvent(listener);
}
catch (JSONException e) { Log.d(TAG, "message " + e); }
}
}
これは私のDiffUtil
クラスがどのように見えるかです:
public class MyDiffUtilCallBack extends DiffUtil.Callback{
ArrayList<User> oldUsers;
ArrayList<User> newUsers;
public MyDiffUtilCallBack(ArrayList<User> newUsers, ArrayList<User> oldUsers) {
this.newUsers = newUsers;
this.oldUsers = oldUsers;
}
@Override
public int getOldListSize() {
return oldUsers.size();
}
@Override
public int getNewListSize() {
return newUsers.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldUsers.get(oldItemPosition).getUserId().equals( newUsers.get(newItemPosition).getUserId());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldUsers.get(oldItemPosition).equals(newUsers.get(newItemPosition));
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
//you can return particular field for changed item.
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
そしてこれは私のアダプターです:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<User> mDataset;
private MyViewHolder myHolder;
private User user;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public ImageView singleItemImage;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemImage = (ImageView) v.findViewById(R.id.icon);
singleItemTextView = (TextView) v.findViewById(R.id.singleitemtv);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.nbConstraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<User> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.nb_image_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
myHolder = holder;
user = mDataset.get(position);
Uri userImage = user.getImageUrl();
myHolder.singleItemTextView.setText(user.getUserId());
Glide.with(myHolder.itemView.getContext() /* context */)
.load(userImage)
.into(myHolder.singleItemImage);
myHolder.constraintLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), DisplayUserActivity.class);
context.startActivity(intent);
}
});
}
public void updateList(ArrayList<User> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffUtilCallBack(this.mDataset, newList));
diffResult.dispatchUpdatesTo(this);
}
}
すべてのクラスを正しく結合するかどうか(初めてDiffUtil
を使用したとき)はわかりません。また、cannot resolve method updateList(?)
も取得します
何が悪いのですか?
これは私のフラグメントでmAdapterを定義する方法です:
public class MyFragment extends Fragment {
private ArrayList<User> myDataset;
private RecyclerView.Adapter mAdapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_lks, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
myDataset = new ArrayList<User>();
mAdapter = new MyAdapter(myDataset);
のように見えますpublic void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads)
未実装DiffUtilsを正しく使用するには、これを実装します。このメソッドは変更に対して呼び出され、ペイロードに基づいて、notifyDataSetChanged()を呼び出す代わりに、recyclerviewアイテムを更新できます。
メソッドを変更します。
public void updateList(ArrayList<User> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffUtilCallBack(this.mDataset, newList));
this.mDataSet.clear()
this.mDataSet.addAll(newList)
diffResult.dispatchUpdatesTo(this);
}