【问题标题】:Android - Retrieve data from Firebase into Listview on Activity LoadAndroid - 在活动加载时将数据从 Firebase 检索到 Listview
【发布时间】:2017-02-12 03:39:46
【问题描述】:

我很难弄清楚这一点。我有一个带有列表视图的活动。我的列表视图使用包含 TextView 和 imageView 的 row_item。

这是我的 Firebase 实时数据库。

这是我的数据对象

public class Spacecraft
{
    private int level;
    private int NumCorrect;

    public Spacecraft()
    {
    }

    public int getLevel() {return level;}
    public void setLevel(int level) {this.level = level;}

    public int getNumCorrect() {return NumCorrect;}
    public void setNumCorrect(int numCorrect) {NumCorrect = numCorrect;}
}

我的 FireBaseHelper 类

public class FirebaseHelper {
    DatabaseReference db;
    Boolean saved;
    ArrayList<Spacecraft> spacecrafts=new ArrayList<>();
    /*
 PASS DATABASE REFRENCE
  */
    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }
    //WRITE IF NOT NULL
    public Boolean save(Spacecraft spacecraft)
    {
        if(spacecraft==null)
        {
            saved=false;
        }else
        {
            try
            {
                db.child("users").push().setValue(spacecraft);
                //db.child("Spacecraft").push().setValue(spacecraft);
                saved=true;
            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved=false;
            }
        }
        return saved;
    }
    //IMPLEMENT FETCH DATA AND FILL ARRAYLIST
    private void fetchData(DataSnapshot dataSnapshot)
    {
        spacecrafts.clear();
        for (DataSnapshot ds : dataSnapshot.getChildren())
        {
            Spacecraft spacecraft=ds.getValue(Spacecraft.class);
            spacecrafts.add(spacecraft);
        }
    }
    //RETRIEVE
    public ArrayList<Spacecraft> 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 spacecrafts;
    }
}

我的自定义适配器

public class CustomAdapter extends BaseAdapter{
    Context c;
    ArrayList<Spacecraft> spacecrafts;
    public CustomAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
        this.c = c;
        this.spacecrafts = spacecrafts;
    }
    @Override
    public int getCount() {
        return spacecrafts.size();
    }
    @Override
    public Object getItem(int position) {
        return spacecrafts.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.list_item,parent,false);
        }
        TextView nameTxt= (TextView) convertView.findViewById(R.id.LevelText);
        //TextView propTxt= (TextView) convertView.findViewById(R.id.propellantTxt);
        //TextView descTxt= (TextView) convertView.findViewById(R.id.descTxt);
        ImageView iv=(ImageView) convertView.findViewById(R.id.imageViewStars);

        final Spacecraft s= (Spacecraft) this.getItem(position);
        nameTxt.setText("Level " + s.getLevel());
        iv.setImageResource(R.drawable.lock);

        return convertView;
    }
}

第一个加载引用列表视图的类...这是一个片段。

public class GoogleAuthentication extends AppCompatActivity implements Serializable,
        GoogleApiClient.OnConnectionFailedListener {

    private static final String TAG = "SignInActivity";
    private static final int RC_SIGN_IN = 9001;
    public final static String USER_ID = "USER_ID";

    private GoogleApiClient mGoogleApiClient;
    private FireBase mFirebase;

    DatabaseReference db;
    FirebaseHelper helper;
    CustomAdapter adapter;

    private TextView mStatusTextView;
    private ProgressDialog mProgressDialog;
    MenuInflater inflater;
    private boolean  mSignedIn;
    private GoogleSignInAccount acct;
    private NumberPicker picker;
    ArrayList Levels;
    String[] LevelsArray;


    ListView lv;

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

        //INITIALIZE FIREBASE DB
        db = FirebaseDatabase.getInstance().getReference();
        helper = new FirebaseHelper(db);
        //ADAPTER
        lv = (ListView) findViewById(R.id.LevelListView);
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();

        // Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();
    }
private void updateUI(boolean signedIn)
    {
        mSignedIn = signedIn;
        if (signedIn)
        {
            Spacecraft s = new Spacecraft();
            s.setLevel(0);


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

            invalidateOptionsMenu();
        } else {
            //mStatusTextView.setText(R.string.signed_out);
        }
    }
}

因此,当 GoogleAuthentication 类加载时,它会初始化并获取对 Firebase 数据库的引用。然后它将用户登录到他们的 Google 帐户。然后 UpdateUI 方法运行。此方法设置 listview 适配器并调用 FireBase Helper 类并运行检索方法。检索方法设置 ChildEventListener。

但是,当所有这些都发生时,我想查询 Firebase 数据库并显示 2 个列表视图行。第一个应该说 2 级,下一个应该说 3 级。根据我现在编写的 GetView 方法的方式,两行都应该显示可绘制的锁。但是,当我现在运行它时,我只看到一个空白屏幕。我可以看到我正在检索数据并填充 ArrayList,但由于某种原因数据没有进入 ListView。任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 关于你的firebase数据库,你需要的是你想在一个列表视图中显示2级的用户,在另一个列表视图中显示3级的用户。是这样吗?

标签: android listview firebase firebase-realtime-database


【解决方案1】:

问题是helper.retrieve() 返回一个空列表。在您的代码中,fetchData 在添加或更改子项时被异步调用。调用 fetch data 时,arraylist 被填满,但在您的适配器上没有更新。

您可能会考虑重新组织您的代码。但是如果你想继续使用当前的代码,我建议你定义一个接口 -

public interface OnDataChangeListener {
    void onDataChanged();
}

让您的FirebaseHelper 类保留一组OnDataChangeListener 对象。

FirebaseHelper中暴露两个方法——

void addDataChangeListener(OnDataChangeListener l);
void removeDataChangeListener(OnDataChangeListener l);

在第一个方法中,添加传递给集合的侦听器对象,然后在第二个方法中从集合中删除引用。 每当fetchData 方法完成时,您可能会遍历OnDataChangeListener 对象集并调用onDataChanged 方法。

让您的适配器类实现OnDataChangeListener 接口并将其设置为FirebaseHelper 类。

基本上,我解释的是你应该实现一个观察者模式。这样每次数据更改时都会通知您的适配器并相应地刷新 UI。

希望这会有所帮助!!!!

【讨论】:

  • 非常感谢。我是一个android新手,所以我决定暂时不使用该界面。相反,我从 FireBaseHelper 类中取出了检索和获取方法,并将它们放入我的 Activity 类中。在我添加 adapter.notifyDataSetChanged(); 之前,这仍然不起作用到我的 ChildEventListener onChildAdded 和 onChildChanged 方法。现在一切正常。
猜你喜欢
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
  • 2016-12-18
  • 1970-01-01
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
相关资源
最近更新 更多