Android Studio Firebase DataChange 异步和捆绑问题 (Java)
Android Studio Firebase DataChange Async and Bundle Issue (Java)
当我从 Firebase 实时数据库调用时,onDataChange
方法出现了某些问题。这些问题包括数据在 DataChange 方法之外消失。我尝试了这个 link 的解决方案,
,它已经起作用了,但是,当我尝试将它传递给回调方法中的片段包时,它说值是 null 并且其中没有任何数据。我面临的这个问题有什么解决方法吗?非常感谢帮助,谢谢!
import edu.ntu.ssp4_rzdns_outhink.R;
import edu.ntu.ssp4_rzdns_outhink.modals.Attraction;
public class MostPopularRecyclerViewAdapter extends RecyclerView.Adapter<MostPopularRecyclerViewAdapter.ViewHolder>{
private static final String TAG = "MostPopularRecyclerViewAdapter";
private static final String SHARED_PREFS = "attractionsFile";
private ArrayList<Attraction> pops;
private Attraction attraction;
private Context mContext;
private FragmentManager fm;
private Bundle bundle;
SharedPreferences.Editor editor;
SharedPreferences attractionFile;
public MostPopularRecyclerViewAdapter(ArrayList<Attraction> pops, Context mContext, FragmentManager fm, Bundle bundle) {
this.pops = pops;
this.mContext = mContext;
this.fm = fm;
this.bundle = bundle;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Log.d(TAG, "OnCreateViewHolder Called");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_more_list, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder Called");
Glide.with(mContext).asBitmap().load(pops.get(position).photo_url).into(holder.attractionImage);
holder.locationName.setText(pops.get(position).att_name);
holder.locationRating.setText(pops.get(position).att_rating.toString());
holder.locationAddress.setText(pops.get(position).att_address);
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String attraction_id = pops.get(holder.getBindingAdapterPosition()).id;
readData(new FirebaseCallback() {
@Override
public void onCallBack(Attraction attr) {
bundle.putString("attid", attr.id);
bundle.putString("name", attr.att_name);
bundle.putString("address", attr.att_address);
bundle.putString("desc", attr.att_desc);
bundle.putDouble("rating", attr.att_rating);
bundle.putString("url", attr.att_url);
bundle.putSerializable("ophrs", attr.att_op_hr);
bundle.putSerializable("adminrate",attr.att_admin_rate);
bundle.putString("photo_url", attr.photo_url);
}
},attraction_id);
}
});
}
@Override
public int getItemCount() {
return pops.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
ImageView attractionImage;
TextView locationName;
TextView locationAddress;
TextView locationRating;
RelativeLayout parentLayout;
public ViewHolder(@NonNull View itemView){
super(itemView);
attractionImage = itemView.findViewById(R.id.viewmoreImage);
locationName = itemView.findViewById(R.id.viewmoreName);
locationAddress = itemView.findViewById(R.id.viewmoreLocation);
locationRating = itemView.findViewById(R.id.viewmoreRating);
parentLayout = itemView.findViewById(R.id.parent_layout_view_more);
}
}
private void readData(FirebaseCallback firebaseCallback, String attrId){
Query query = FirebaseDatabase.getInstance().getReference("attractions");
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (!snapshot.exists()) {
System.out.println("Attraction Does Not Exist");
} else {
for (DataSnapshot attr : snapshot.getChildren()) {
if (attr.getKey().equals(attrId)) {
attraction = attr.getValue(Attraction.class);
attraction.setId(attr.getKey());
}
}
firebaseCallback.onCallBack(attraction);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
private interface FirebaseCallback{
void onCallBack(Attraction attraction);
}
}
根据您最后的评论:
When I try to put these variables in the bundle, it’ll just disappear and become null.
请注意,这是预期的行为。您的代码中存在多个不一致之处。首先,这不是您处理适配器 class 中的点击事件的方式。将点击侦听器附加到您显示的每个元素并不是一个可行的解决方案。您应该为此创建一个界面,如您在 repo.
中所见
现在,每次单击 RecyclerView 中的特定元素时,都会调用 readData()
方法。当您收到数据时,您将该数据添加到 Bundle 中。问题是打开新片段的操作比您从数据库中获取数据的速度更快。这就是你得到 null 的原因。
要解决这个问题,您可以导航到下一个片段,仅当数据可用时,或者您可以直接从第二个片段进行另一个调用。
当我从 Firebase 实时数据库调用时,onDataChange
方法出现了某些问题。这些问题包括数据在 DataChange 方法之外消失。我尝试了这个 link 的解决方案,
import edu.ntu.ssp4_rzdns_outhink.R;
import edu.ntu.ssp4_rzdns_outhink.modals.Attraction;
public class MostPopularRecyclerViewAdapter extends RecyclerView.Adapter<MostPopularRecyclerViewAdapter.ViewHolder>{
private static final String TAG = "MostPopularRecyclerViewAdapter";
private static final String SHARED_PREFS = "attractionsFile";
private ArrayList<Attraction> pops;
private Attraction attraction;
private Context mContext;
private FragmentManager fm;
private Bundle bundle;
SharedPreferences.Editor editor;
SharedPreferences attractionFile;
public MostPopularRecyclerViewAdapter(ArrayList<Attraction> pops, Context mContext, FragmentManager fm, Bundle bundle) {
this.pops = pops;
this.mContext = mContext;
this.fm = fm;
this.bundle = bundle;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Log.d(TAG, "OnCreateViewHolder Called");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_more_list, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder Called");
Glide.with(mContext).asBitmap().load(pops.get(position).photo_url).into(holder.attractionImage);
holder.locationName.setText(pops.get(position).att_name);
holder.locationRating.setText(pops.get(position).att_rating.toString());
holder.locationAddress.setText(pops.get(position).att_address);
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String attraction_id = pops.get(holder.getBindingAdapterPosition()).id;
readData(new FirebaseCallback() {
@Override
public void onCallBack(Attraction attr) {
bundle.putString("attid", attr.id);
bundle.putString("name", attr.att_name);
bundle.putString("address", attr.att_address);
bundle.putString("desc", attr.att_desc);
bundle.putDouble("rating", attr.att_rating);
bundle.putString("url", attr.att_url);
bundle.putSerializable("ophrs", attr.att_op_hr);
bundle.putSerializable("adminrate",attr.att_admin_rate);
bundle.putString("photo_url", attr.photo_url);
}
},attraction_id);
}
});
}
@Override
public int getItemCount() {
return pops.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
ImageView attractionImage;
TextView locationName;
TextView locationAddress;
TextView locationRating;
RelativeLayout parentLayout;
public ViewHolder(@NonNull View itemView){
super(itemView);
attractionImage = itemView.findViewById(R.id.viewmoreImage);
locationName = itemView.findViewById(R.id.viewmoreName);
locationAddress = itemView.findViewById(R.id.viewmoreLocation);
locationRating = itemView.findViewById(R.id.viewmoreRating);
parentLayout = itemView.findViewById(R.id.parent_layout_view_more);
}
}
private void readData(FirebaseCallback firebaseCallback, String attrId){
Query query = FirebaseDatabase.getInstance().getReference("attractions");
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (!snapshot.exists()) {
System.out.println("Attraction Does Not Exist");
} else {
for (DataSnapshot attr : snapshot.getChildren()) {
if (attr.getKey().equals(attrId)) {
attraction = attr.getValue(Attraction.class);
attraction.setId(attr.getKey());
}
}
firebaseCallback.onCallBack(attraction);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
private interface FirebaseCallback{
void onCallBack(Attraction attraction);
}
}
根据您最后的评论:
When I try to put these variables in the bundle, it’ll just disappear and become null.
请注意,这是预期的行为。您的代码中存在多个不一致之处。首先,这不是您处理适配器 class 中的点击事件的方式。将点击侦听器附加到您显示的每个元素并不是一个可行的解决方案。您应该为此创建一个界面,如您在 repo.
中所见现在,每次单击 RecyclerView 中的特定元素时,都会调用 readData()
方法。当您收到数据时,您将该数据添加到 Bundle 中。问题是打开新片段的操作比您从数据库中获取数据的速度更快。这就是你得到 null 的原因。
要解决这个问题,您可以导航到下一个片段,仅当数据可用时,或者您可以直接从第二个片段进行另一个调用。