2016-12-13 23 views
3

Я пытаюсь создать RecyclerView в режиме реального времени каждый раз, когда пользователь добавляет элемент к определенной ссылке базы данных в Firebase. Вот мой класс модели:Firebase RecyclerView не загружает новые данные

@IgnoreExtraProperties 
public class Poll { 

private String question; 
private String image_URL; 

public Poll() { 
} 

public Poll(String Question, String Image_URL){ 
    this.question = Question; 
    this.image_URL = Image_URL; 
} 


public String getQuestion() { 
    return question; 
} 

public void setQuestion(String question) { 
    question = question; 
} 

public String getImage_URL() { 
    return image_URL; 
} 

public void setImage_URL(String image_URL) { 
    image_URL = image_URL; 
} 

@Exclude 
public Map<String, Object> toMap(){ 
    HashMap<String, Object> result = new HashMap<>(); 
    result.put("question", question); 
    result.put("image_URL", image_URL); 
    return result; 
} 

Вот класс, в котором я сохраняю данные в Firebase. Это на самом деле записывается в 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; 
      } 

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

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

Я хочу recyclerview жить обновления на всех устройствах, как добавляется элемент. Вот фрагмент, который я использую для заполнения RecyclerView с использованием библиотеки интерфейса Firebase. Как добавить данные/записи в Firebase, как указано в предыдущем фрагменте кода, я не вижу никаких живых обновления на любых устройствах:

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 FirebaseRecyclerAdapter <Poll, PollHolder> mFireAdapter; 


// 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); 
    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); 
    mRecyclerview = (RecyclerView) v.findViewById(R.id.new_RecyclerView); 
    mBaseRef = FirebaseDatabase.getInstance().getReference(); 
    mPollsRef = mBaseRef.child("Polls"); 

    if (mRecyclerview != null){ 
     mRecyclerview.setHasFixedSize(true); 
    } 

    mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext()); 
    mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL 
    ); 

    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); 
    } 
} 

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

    mFireAdapter = new FirebaseRecyclerAdapter<Poll, PollHolder>(
      Poll.class, 
      R.layout.latest_item, 
      PollHolder.class, 
      mPollsRef 
    ){ 

     @Override 
     protected void populateViewHolder(PollHolder viewHolder, Poll model, int position) { 
      viewHolder.mPollQuestion.setText(model.getQuestion()); 
      Picasso.with(getActivity().getApplicationContext()) 
        .load(model.getImage_URL()) 
        .fit() 
        .into(viewHolder.mPollImage); 
      Log.v("QUESTION", model.getQuestion()); 
      Log.v("IMAGE", model.getImage_URL()); 

     } 
    }; 

    mRecyclerview.setAdapter(mFireAdapter); 
} 

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

@Override 
public void onAttach(Context context) { 
    super.onAttach(context); 
    if (context instanceof OnFragmentInteractionListener) { 
     mListener = (OnFragmentInteractionListener) context; 
    } else { 
     throw new RuntimeException(context.toString() 
       + " must implement OnFragmentInteractionListener"); 
    } 
} 

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


public static class PollHolder extends RecyclerView.ViewHolder { 

    TextView mPollQuestion; 
    ImageView mPollImage; 


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

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

    } 
} 

/** 
* This interface must be implemented by activities that contain this 
* fragment to allow an interaction in this fragment to be communicated 
* to the activity and potentially other fragments contained in that 
* activity. 
* <p> 
* See the Android Training lesson <a href= 
* "http://developer.android.com/training/basics/fragments/communicating.html" 
* >Communicating with Other Fragments</a> for more information. 
*/ 
public interface OnFragmentInteractionListener { 
    // TODO: Update argument type and name 
    void onFragmentInteraction(Uri uri); 
    } 
} 

EDIT: Я считаю, что данные, записанные в Firebase является недействительным по какой-то причине, поскольку журналы для Question и ImageURL не возвращают никаких данных.

+0

Вы используете [Firebase Console] (https://console.firebase.google.com/) для проверки базы данных проекта и подтверждения ожидаемых изменений? –

+0

База данных в консоли Firebase записывается правильно, она не читается в реализации RecyclerView. – tccpg288

+1

В этом случае этот оператор в вашем сообщении вводит в заблуждение: _I полагает, что данные, записываемые в Firebase, по какой-то причине являются нулями –

ответ

1

Ваши Poll сеттеров отсутствуют this:

public void setQuestion(String question) { 
    this.question = question; 
} 

public void setImage_URL(String image_URL) { 
    this.image_URL = image_URL; 
} 

И заменить этот код:

Map <String, Object> pollMap = poll.toMap(); 
    String key = mBaseRef.child("Polls").push().getKey(); 
    Map<String, Object> childUpdates = new HashMap<String, Object>(); 
    childUpdates.put("/Polls/" + key, pollMap); 
    mBaseRef.updateChildren(childUpdates); 

с:

mBaseRef.child("Polls").push().setValue(poll, new DatabaseReference.CompletionListener() { 
    @Override 
    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { 
     if (databaseError == null) { 
      Log.i("Poll", "onComplete: SUCCESS"); 
     } else { 
      Log.w("Poll", "onComplete: ", databaseError.toException()); 
     } 
    } 
}); 

Также переместим код, который создает mFireAdapter и устанавливает его по mRecyclerview от onStart() до конца onCreateView():

//... 
mRecyclerview.setLayoutManager(mLayoutManager); 
mFireAdapter = ...; 
mRecyclerview.setAdapter(mFireAdapter); 

return v; 

Документация provides an example.

+0

. Очень ценю помощь, но RecyclerView все еще не заселяется вживую. Должен ли я добавлять один прослушиватель событий в метод .onCreate() для загрузки элементов recyclerview изначально? При вращении экрана элементы действительно заполняются в RecyclerView, что является странным. Это как если бы .onStart() не вызывается, если я не поворачиваю экран ... – tccpg288

+0

Я думаю, что еще одна проблема связана с тем, что я загружаю фрагменты, а когда я нахожусь во втором фрагменте на моей вкладке, это вызывая onStart в третьем фрагменте. В конечном счете, onStart() не запускается в нужное время – tccpg288

+0

Я тоже вижу эту ошибку: 12-12 20: 42: 24.285 27961-27961/com.troychuinard.fanpolls E/RecyclerView: адаптор не подключен; пропуская макет – tccpg288