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 的原因。

要解决这个问题,您可以导航到下一个片段,仅当数据可用时,或者您可以直接从第二个片段进行另一个调用。