Firebase RecylcerView适配器不准确查看位置 [英] Firebase RecylcerView Adapter Not Getting Accurate View Position

查看:155
本文介绍了Firebase RecylcerView适配器不准确查看位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firebase用户界面,并遇到一个独特的问题。当我加载RecyclerView时,没有问题。我单击RecyclerView上的一个项目,并获取被点击的项目的.push()值。然后,从Firebase .push()值中获取数据,该数据存储在Firebase数据库中,并将其发送到其他活动。见下图:






第二个图像是通过意图接收数据的活动。当我点击回到RecyclerView时,我再次点击8,我加载了一个不同的数字(现在看起来是1)。

最终,我担心我没有正确设置RecyclerView。这是我的代码:

创建轮询对象(PO​​JO)并写入到Firebase:

  mSubmitPollCreation.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){

// TODO:需要检查if如果(resultImageURL == null){
Toast.makeText(getApplicationContext()),则会添加轮询要求,即问题,答案,......
//检查图像是否已经被首先加载
if (),getResources()。getString(R.string.no_image_selected),Toast.LENGTH_LONG).show();
return;
}

//捕获答案
if(mNumberOfPollAnswersCreatedByUser> 5){
Toast.makeText(getApplicationContext(),getResources().getText(R.string.poll_answers_greater_than_five),Toast.LENGTH_LONG).show();
mNumberOfPollAnswersCreatedByUser = 5;
}
for(int i = 0;我< mNumberOfPollAnswersCreatedByUser; (+ +));}};}};}};}};
String editTextInputForAnswer = String.valueOf(editText.getText());
mPollAnswers.add(0,editTextInputForAnswer); Toast.makeText(getApplicationContext(),editTextInputForAnswer,Toast.LENGTH_SHORT).show();


$ b $ poll poll = new Poll(mCreatePollQuestion.getText()。toString(),resultImageURL,mPollAnswers);
地图< String,Object> pollMap = poll.toMap();
final String key = mBaseRef.child(Polls)。push()。getKey();
地图< String,Object> childUpdates = new HashMap< String,Object>();
childUpdates.put(/ Polls /+ key,pollMap);

mBaseRef.updateChildren(childUpdates);
Collections.reverse(mPollAnswers); $($)$ b $ for(int i = 0; i mBaseRef.child(Polls)。child(key).child(answers)。child String.valueOf(i + 1))。updateChildren(poll.answerConvert(mPollAnswers,i));
}

Intent toHomeActivity = new Intent(CreateActivity.this,HomeActivity.class);
toHomeActivity.putExtra(viewpager_position,2);
startActivity(toHomeActivity);
}
});

在Firebase中阅读并填充RecyclerView:

  public class LiveFragment extends Fragment {
// TODO:重命名参数参数,选择匹配
的名字//片段初始化参数,例如ARG_ITEM_NUMBER
private static final String ARG_PARAM1 =param1;
private static final String ARG_PARAM2 =param2;

private RecyclerView mRecyclerview;
私人DatabaseReference mBaseRef;
private DatabaseReference mPollsRef;
私有LinearLayoutManager mLayoutManager;
私人FloatingActionButton mFloatingActionAdd;

private FirebaseRecyclerAdapter< Poll,PollHolder> mFireAdapter;

private RecyclerView.ItemAnimator mItemAnimator;


// TODO:重命名和更改参数类型
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public LiveFragment(){
//所需的空公共构造函数

$ b $ **
*使用此工厂方法创建
*这个片段的新实例使用提供的参数。
*
* @param param1参数1.
* @param param2参数2.
* @return片段LiveFragment的新实例。
* /
// TODO:重命名和更改参数的类型和数量
public static LiveFragment newInstance(String param1,String param2){
LiveFragment fragment = new LiveFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1,param1);
args.putString(ARG_PARAM2,param2);
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mBaseRef = FirebaseDatabase.getInstance()。getReference();
mPollsRef = mBaseRef.child(Polls); $($ get


mParam2 = getArguments()。getString(ARG_PARAM2);



$覆盖
公共视图onCreateView(LayoutInflater inflater,ViewGroup容器,
Bundle savedInstanceState){
//膨胀这个片段的布局
final View v = inflater.inflate(R.layout.fragment_new,container,false);
Log.v(TAG,ON CREATE CALLED FROM NEW);

mRecyclerview =(RecyclerView)v.findViewById(R.id.list);
mRecyclerview.setItemAnimator(new SlideInLeftAnimator());


mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mFloatingActionAdd =(FloatingActionButton)getActivity()。findViewById(R.id.myFAB);
mFloatingActionAdd.setOnClickListener(new View.OnClickListener(){
@Override $ b $ public void onClick(View v){
Intent I = new Intent(getActivity()。getApplicationContext() ,CreateActivity.class);
startActivity(I);
}
});


mRecyclerview.setLayoutManager(mLayoutManager);
return v;

$ b $ // TODO:将方法,更新参数和钩子方法重命名为UI事件
public void onButtonPressed(Uri uri){
if(mListener!= null ){
mListener.onFragmentInteraction(uri);
}
scrollToPosition();


@Override
public void onStart(){
super.onStart();

mFireAdapter = new FirebaseRecyclerAdapter< Poll,PollHolder>(Poll.class,R.layout.latest_item,PollHolder.class,mBaseRef.child(Polls)){
@Override
protected void populateViewHolder(PollHolder viewHolder,final Poll model,final int position){
viewHolder.mPollQuestion.setText(model.getQuestion());
Picasso.with(getActivity()。getApplicationContext())
.load(model.getImage_URL())
.fit()$ b $ .into(viewHolder.mPollImage);
viewHolder.mView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Log.v(TAG,model.toString ());
Log.v(TAG,ONCLICKED);
Intent toPoll = new Intent(getActivity(),PollHostActivity.class);
toPoll.putExtra(POLL_ID ,mFireAdapter.getRef(position).getKey());
startActivity(toPoll);


});
Log.v(TAG,mFireAdapter.getRef(position).getKey());
Log.v(TAG,String.valueOf(position));
Log.v(TAG,model.getQuestion());
Log.v(TAG,model.getImage_URL());
}
};

mRecyclerview.setAdapter(mFireAdapter);
scrollToPosition();




$ b @Override
public void onStop(){
super.onStop();
if(mFireAdapter!= null){
mFireAdapter.cleanup();



$ b @Override
public void onDetach(){
super.onDetach();
mListener = null;



public static class PollHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

TextView mPollQuestion;
ImageView mPollImage;
查看mView;


public PollHolder(查看itemView){
super(itemView);

mPollQuestion =(TextView)itemView.findViewById(R.id.latest_item_question);
mPollImage =(ImageView)itemView.findViewById(R.id.pollThumbNailImage);
this.mView = itemView;
itemView.setOnClickListener(this);


$ b @Override
public void onClick(View view){
Log.v(TAG,CLICKED);



$ b private void scrollToPosition(){
mFireAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver(){
@Override
public void onItemRangeInserted(int positionStart,int itemCount){
super.onItemRangeInserted(positionStart,itemCount);
int pollCount = mFireAdapter.getItemCount();
int lastVisiblePosition = mLayoutManager.findLastCompletelyVisibleItemPosition ();

//如果最初正在加载回收站视图,或者用户位于列表底部,请将
//滚动到列表底部以显示新添加的消息。
if(lastVisiblePosition == -1 ||
(positionStart> =(pollCount - 1)&& amp; lastVisiblePosition ==(positionStart - 1))){
mRecyclerview。 scrollToPosition(positionStart);
}
}
});


$ / code $ / pre

我的想法:


  1. 我是否在正确的位置调用mFireAdapter.cleanup()?

  2. 点击8,看到1没有出现在RecyclerView的第一个负载上,只有当我从活动(第二个图像)返回到RecyclerView时才会发生。


  3. 我调用.setStackFromEnd(true)和.setReverseLayout(true)来反转存储在FirebaseDatabase中的数据,这可能是导致问题的原因。


  4. 我在.populateViewHolder()方法中设置了.setOnClickListener(),并使用以下命令将.push()键以意向方式传递给下一个活动:

      toPoll.putExtra(POLL_ID,mFireAdapter.getRef(position).getKey()); 


这种方法可能会得到不正确的键。

最后,Firebase数据库:



任何帮助将不胜感激!

解决方案

$ c>位置之外 populateViewHolder ,因为它的值可能不同。相反,使你的 viewHolder final并使用 viewHolder.getAdapterPosition()来取代它。 b

I am using the Firebase UI and am experiencing a unique issue. When I load the RecyclerView, there are no issues. I click an item on the RecyclerView and get the .push() value of the item that was clicked. It then takes data from that Firebase .push() value, which is stored in the Firebase database, and sends it to another activity. See images below:

The second image is the activity that receives data via an intent. When I click back to the RecyclerView, I click "8" again and I am loading a different number (right now it appears to be 1).

Ultimately, I am concerned that I do not have the RecyclerView set up correctly. Here is my code:

Create Poll object (POJO) and write to Firebase:

        mSubmitPollCreation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            //TODO: Need to check if poll requirements are added, i.e. Question, Answer, ......
            //check if image has been loaded first
            if (resultImageURL == null) {
                Toast.makeText(getApplicationContext(), getResources().getString(R.string.no_image_selected), Toast.LENGTH_LONG).show();
                return;
            }

            //capture answers
            if (mNumberOfPollAnswersCreatedByUser > 5) {
                Toast.makeText(getApplicationContext(), getResources().getText(R.string.poll_answers_greater_than_five), Toast.LENGTH_LONG).show();
                mNumberOfPollAnswersCreatedByUser = 5;
            }
            for (int i = 0; i < mNumberOfPollAnswersCreatedByUser; i++) {
                EditText editText = (EditText) mEditTextAnswerLayout.findViewWithTag(getResources().getString(R.string.created_answer_editText_id) + String.valueOf(i + 1));
                String editTextInputForAnswer = String.valueOf(editText.getText());
                mPollAnswers.add(0, editTextInputForAnswer);                 Toast.makeText(getApplicationContext(),editTextInputForAnswer,Toast.LENGTH_SHORT).show();
            }


            Poll poll = new Poll(mCreatePollQuestion.getText().toString(), resultImageURL, mPollAnswers);
            Map<String, Object> pollMap = poll.toMap();
            final String key = mBaseRef.child("Polls").push().getKey();
            Map<String, Object> childUpdates = new HashMap<String, Object>();
            childUpdates.put("/Polls/" + key, pollMap);

            mBaseRef.updateChildren(childUpdates);
            Collections.reverse(mPollAnswers);
            for (int i = 0; i < mPollAnswers.size(); i++) {
                mBaseRef.child("Polls").child(key).child("answers").child(String.valueOf(i + 1)).updateChildren(poll.answerConvert(mPollAnswers, i));
            }

            Intent toHomeActivity = new Intent(CreateActivity.this, HomeActivity.class);
            toHomeActivity.putExtra("viewpager_position", 2);
            startActivity(toHomeActivity);
        }
    });

Where I read from Firebase and populate a RecyclerView:

public class LiveFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

private RecyclerView mRecyclerview;
private DatabaseReference mBaseRef;
private DatabaseReference mPollsRef;
private LinearLayoutManager mLayoutManager;
private FloatingActionButton mFloatingActionAdd;

private FirebaseRecyclerAdapter<Poll, PollHolder> mFireAdapter;

private RecyclerView.ItemAnimator mItemAnimator;


// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public LiveFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment LiveFragment.
 */
// TODO: Rename and change types and number of parameters
public static LiveFragment newInstance(String param1, String param2) {
    LiveFragment fragment = new LiveFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mBaseRef = FirebaseDatabase.getInstance().getReference();
    mPollsRef = mBaseRef.child("Polls");

    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    final View v = inflater.inflate(R.layout.fragment_new, container, false);
    Log.v("TAG", "ON CREATE CALLED FROM NEW");

    mRecyclerview = (RecyclerView) v.findViewById(R.id.list);
    mRecyclerview.setItemAnimator(new SlideInLeftAnimator());


    mLayoutManager = new LinearLayoutManager(getContext());
    mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mLayoutManager.setReverseLayout(true);
    mLayoutManager.setStackFromEnd(true);

    mFloatingActionAdd = (FloatingActionButton) getActivity().findViewById(R.id.myFAB);
    mFloatingActionAdd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent I = new Intent(getActivity().getApplicationContext(), CreateActivity.class);
            startActivity(I);
        }
    });


    mRecyclerview.setLayoutManager(mLayoutManager);
    return v;
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
    scrollToPosition();
}

@Override
public void onStart() {
    super.onStart();

    mFireAdapter = new FirebaseRecyclerAdapter<Poll, PollHolder>(Poll.class, R.layout.latest_item, PollHolder.class, mBaseRef.child("Polls")) {
        @Override
        protected void populateViewHolder(PollHolder viewHolder, final Poll model, final int position) {
            viewHolder.mPollQuestion.setText(model.getQuestion());
            Picasso.with(getActivity().getApplicationContext())
                    .load(model.getImage_URL())
                    .fit()
                    .into(viewHolder.mPollImage);
            viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.v("TAG", model.toString());
                    Log.v("TAG","ONCLICKED");
                    Intent toPoll = new Intent(getActivity(), PollHostActivity.class);
                    toPoll.putExtra("POLL_ID", mFireAdapter.getRef(position).getKey());
                    startActivity(toPoll);

                }
            });
            Log.v("TAG", mFireAdapter.getRef(position).getKey());
            Log.v("TAG", String.valueOf(position));
            Log.v("TAG", model.getQuestion());
            Log.v("TAG", model.getImage_URL());
        }
    };

    mRecyclerview.setAdapter(mFireAdapter);
    scrollToPosition();



}

@Override
public void onStop() {
    super.onStop();
    if (mFireAdapter != null) {
        mFireAdapter.cleanup();
    }
}


@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}


public static class PollHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView mPollQuestion;
    ImageView mPollImage;
    View mView;


    public PollHolder(View itemView) {
        super(itemView);

        mPollQuestion = (TextView) itemView.findViewById(R.id.latest_item_question);
        mPollImage = (ImageView) itemView.findViewById(R.id.pollThumbNailImage);
        this.mView = itemView;
        itemView.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        Log.v("TAG", "CLICKED");
    }
}


private void scrollToPosition(){
    mFireAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            int pollCount = mFireAdapter.getItemCount();
            int lastVisiblePosition = mLayoutManager.findLastCompletelyVisibleItemPosition();

            // If the recycler view is initially being loaded or the user is at the bottom of the list, scroll
            // to the bottom of the list to show the newly added message.
            if (lastVisiblePosition == -1 ||
                    (positionStart >= (pollCount - 1) && lastVisiblePosition == (positionStart - 1))) {
                mRecyclerview.scrollToPosition(positionStart);
            }
        }
    });
   }
}

My thoughts:

  1. am I calling mFireAdapter.cleanup() in the right location?

  2. The issue with clicking "8" and seeing "1" does not appear on the first load of the RecyclerView, it only happens when I go from the activity (second image) and the navigate back to the RecyclerView.

  3. I call .setStackFromEnd(true) and .setReverseLayout(true) to reverse the data as it is stored in the FirebaseDatabase, which could be contributing to the issue.

  4. I set up the .setOnClickListener() in the .populateViewHolder() method, and use the following to pass the .push() key in an intent to the next activity:

      toPoll.putExtra("POLL_ID", mFireAdapter.getRef(position).getKey());
    

This method could be getting the incorrect key.

Finally, Firebase Database:

Any help would be appreciated!

解决方案

You should not use position outside of populateViewHolder as it value may differ. Instead, make your viewHolder final and use viewHolder.getAdapterPosition() to replace it.

这篇关于Firebase RecylcerView适配器不准确查看位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆