2016-08-10 4 views
0

У меня есть пользовательский listview для отображения данных из базы данных Firebase.Android - отображать данные в базе данных ListView из базы Firebase

SectionDetails модель

public class SectionDetails { 
    private String sectionCode; 
    private String sectionSeats; 

public SectionDetails() { 
} 

public SectionDetails(String sectionCode, String sectionSeats) { 
    this.sectionCode = sectionCode; 
    this.sectionSeats = sectionSeats; 
} 

public String getSectionCode() { 
    return sectionCode; 
} 

public String getSectionSeats() { 
    return sectionSeats; 
} 

public void setSectionCode(String sectionCode) { 
    this.sectionCode = sectionCode; 
} 

public void setSectionSeats(String sectionSeats) { 
    this.sectionSeats = sectionSeats; 
} 
} 

FirebaseHelper класс

public class FirebaseHelper { 
     DatabaseReference db; 
     Boolean saved; 
     ArrayList<SectionDetails> sectionDetailsArrayList = new ArrayList<>(); 

    public FirebaseHelper(DatabaseReference db) { 
     this.db = db; 
    } 

    public Boolean save(SectionDetails sectionDetails) { 

     if (sectionDetails == null) { 
      saved = false; 
     } else { 
      try { 
       db.push().setValue(sectionDetails); 
       saved = true; 

       adapter.notifyDataSetChanged(); 

      } catch(DatabaseException e) { 
       e.printStackTrace(); 
       saved = false; 
      } 
     } 

     return saved; 
    } 

    private void fetchData(DataSnapshot dataSnapshot) { 
     sectionDetailsArrayList.clear(); 

     SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class); 
     sectionDetailsArrayList.add(sectionDetails); 
    } 

    public ArrayList<SectionDetails> retrieve() { 
     db.addChildEventListener(new ChildEventListener() { 
      @Override 
      public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
       fetchData(dataSnapshot); 
      } 

      @Override 
      public void onChildChanged(DataSnapshot dataSnapshot, String s) { 
       fetchData(dataSnapshot); 
      } 

      @Override 
      public void onChildRemoved(DataSnapshot dataSnapshot) { 

      } 

      @Override 
      public void onChildMoved(DataSnapshot dataSnapshot, String s) { 

      } 

      @Override 
      public void onCancelled(DatabaseError databaseError) { 

      } 
     }); 
     return sectionDetailsArrayList; 
    } 
} 

CustomAdapter класс

public class CustomAdapter extends BaseAdapter { 
     Context c; 
     ArrayList<SectionDetails> sectionDetailsArrayList; 

    public CustomAdapter(Context c, ArrayList<SectionDetails> sectionDetailsArrayList) { 
     this.c = c; 
     this.sectionDetailsArrayList = sectionDetailsArrayList; 
    } 

    @Override 
    public int getCount() { 
     return sectionDetailsArrayList.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return sectionDetailsArrayList.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     if (convertView == null) { 
      convertView = LayoutInflater.from(c).inflate(R.layout.sections_custom_listview, parent, false); 
     } 

     TextView lvTvSectionCode = (TextView) convertView.findViewById(R.id.lvTvSectionCode); 
     TextView lvTvSectionSeats = (TextView) convertView.findViewById(R.id.lvTvSectionSeats); 

     final SectionDetails sd = (SectionDetails) this.getItem(position); 

     lvTvSectionCode.setText(sd.getSectionCode()); 
     lvTvSectionSeats.setText("allocated seats: " + sd.getSectionSeats()); 

     convertView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Toast.makeText(c, sd.getSectionCode(), Toast.LENGTH_LONG).show(); 
      } 
     }); 

     return convertView; 
    } 
} 

MainActivity класс

public class AddSection extends AppCompatActivity implements View.OnClickListener { 

DatabaseReference mRef; 
FirebaseHelper helper; 
CustomAdapter adapter; 
Button btnCreateSection; 
ListView lvSectionsListOne; 
String getFullSection, seats; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_add_section); 

    lvSectionsListOne = (ListView) findViewById(R.id.lvSectionsList); 

    mRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections"); 
    helper = new FirebaseHelper(mRef); 

    adapter = new CustomAdapter(this, helper.retrieve()); 
    lvSectionsListOne.setAdapter(adapter); 

    btnCreateSection = (Button) findViewById(R.id.btnCreateSection); 
    btnCreateSection.setOnClickListener(this); 

} 

@Override 
public void onClick(View v) { 
    if (v == btnCreateSection) { 

     getFullSection = "section 1A"; 
     seats = "20"; 

     SectionDetails sectionDetails = new SectionDetails(getFullSection, seats); 

      if (helper.save(sectionDetails)) { 

       adapter = new CustomAdapter(AddSection.this, helper.retrieve()); 
       lvSectionsListOne.setAdapter(adapter); 

       adapter.notifyDataSetChanged(); 

      } 
    } 
} 
} 

Я отправил аналогичный вопрос here, но эта проблема другая. Когда добавляются первые данные, в listview ничего не отображается. При добавлении вторых данных первые данные отображаются в listview. И когда добавляются третьи данные, первые данные заменяются вторыми данными, а вторая информация показана в listview. Я попытался добавить adapter.notifyDataSetChanged(), но все тот же результат.

+0

Как насчет базы данных, дети добавляются как ожидалось или заменяются? – 0p3n5ourcE

+0

Hi again @openSource :) Дети добавляются как ожидалось –

+0

Я думаю, что проблема здесь в том, что она не ждет достаточно, пока Firebase не извлечет данные, поэтому, скорее всего, проблема с методом retrieve() в вспомогательном классе похожа на http: //stackoverflow.com/questions/30659569/wait-until-firebase-retrieves-data – 0p3n5ourcE

ответ

3

Данные извлекаются (и синхронизируются) из базы данных Firebase в ваше приложение асинхронно. Это означает, что ваш sectionDetailsArrayList может быть изменен в любое время. Когда вы изменяете данные, вам необходимо сообщить об этом адаптеру, чтобы он мог обновить представление.

private void fetchData(DataSnapshot dataSnapshot) { 
    sectionDetailsArrayList.clear(); 

    SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class); 
    sectionDetailsArrayList.add(sectionDetails); 

    // tell the adapter that we changed its data 
    adapter.notifyDataSetChanged(); 
} 

Это должно обновить представление. Но поскольку вы очищаете список для каждого добавленного или измененного дочернего элемента, приложение будет показывать только последний добавленный/измененный элемент.

Настройка синхронизированного массива в Firebase в некоторой степени задействована, так как вам приходится иметь дело со всеми типами событий и с тем, что evens может произойти в любом порядке. По этой причине мы создаем FirebaseUI library, which contains adapters from the Firebase Database to a ListView and RecyclerView.

Смежные вопросы