如何在 Android 中使用 MVC 模式从 firebase 检索数据? [复制]

Posted

技术标签:

【中文标题】如何在 Android 中使用 MVC 模式从 firebase 检索数据? [复制]【英文标题】:How to retrieve data from firebase using MVC pattern in Android? [duplicate] 【发布时间】:2018-08-14 22:57:10 【问题描述】:

我正在开发一个简单的 android 项目,该项目可以从 Firebase 插入和检索数据。插入功能运行良好,这意味着项目已成功连接到 Firebase 数据库。但是,检索部分不起作用。我做了很多测试,认为问题出在 FirebaseHelper 中,因为当我尝试在 Activity 中打印“firebasehelper.retrieveMajor()”的结果时,它什么也没显示。但它确实在 FirebaseHelper 中打印数据时显示了数据。可以看到如下代码。

型号:

@IgnoreExtraProperties
public class Major 

    public String major_id;
    public String major_name;

    public Major() 
    

    public Major(String major_id, String major_name) 
        this.major_id = major_id;
        this.major_name = major_name;
    

    public String getMajor_id() 
        return major_id;
    

    public String getMajor_name() 
        return major_name;
    

适配器:

public class MajorListAdapter extends BaseAdapter 
    Context context;
    ArrayList<Major> majors;

    public MajorListAdapter(Context context, ArrayList<Major> majors) 
        this.context = context;
        this.majors = majors;
    

    @Override
    public int getCount() 
        return majors.size();
    

    @Override
    public Object getItem(int pos) 
        return majors.get(pos);
    

    @Override
    public long getItemId(int pos) 
        return pos;
    

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) 

        if(convertView==null)
        
            convertView= LayoutInflater.from(context).inflate(R.layout.model,viewGroup,false);
        

        TextView tv_majorid= (TextView) convertView.findViewById(R.id.tx_majorid);
        TextView tv_majorname= (TextView) convertView.findViewById(R.id.tx_majorname);

        final Major major= (Major) this.getItem(position);

        tv_majorid.setText(major.getMajor_id());
        tv_majorname.setText(major.getMajor_name());

        return convertView;
    


FirebaseHelper:

public class FirebaseHelper 

    DatabaseReference db;
    Boolean saved=null;
    ArrayList<Major> majors = new ArrayList<>();

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

    //Save the Major info. into db
    public Boolean saveMajor(Major major)
    
        if(major==null)
        
            saved=false;
        else
        
            try
            
                db.child("Major").push().setValue(major);
                saved=true;

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

        return saved;
    

    private void fetchDataFromMajor(DataSnapshot dataSnapshot) 
        majors.clear();

        for (DataSnapshot ds : dataSnapshot.getChildren()) 
            Major major = ds.getValue(Major.class);
            majors.add(major);
        

    

    public ArrayList<Major> retrieveMajor() 

        db.addChildEventListener(new ChildEventListener() 
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) 
                fetchDataFromMajor(dataSnapshot);                  
            

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) 
                fetchDataFromMajor(dataSnapshot);

            

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) 

            

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

            

            @Override
            public void onCancelled(DatabaseError databaseError) 

            
        );


        return majors;
    

获取数据并将数据与ListView绑定的Activity:

public class MajorListActivity extends AppCompatActivity 

    DatabaseReference db;
    FirebaseHelper firebasehelper;
    MajorListAdapter adapter;
    ListView lv_MajorList;

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

        lv_MajorList = (ListView) findViewById(R.id.lv_MajorList);

        db= FirebaseDatabase.getInstance().getReference();
        firebasehelper=new FirebaseHelper(db);

        //ADAPTER
        adapter = new MajorListAdapter(getApplicationContext(),firebasehelper.retrieveMajor());

        lv_MajorList.setAdapter(adapter);
    


【问题讨论】:

【参考方案1】:

Firebase API 是异步的,这意味着它们会在您的查询结果完成之前立即返回。一段时间后,将使用结果调用您的回调。这意味着您的 retrieveMajor 函数在查询完成之前返回数组 majors 中的任何内容。

您需要正确处理 Firebase API 的异步特性,这意味着您不能编写直接返回从数据库获取的数据的方法。您必须使用回调来等待结果,然后根据需要更新您的 UI。

如需详细了解 Firebase API 为何是异步的以及对它们的期望,read this article。

【讨论】:

谢谢。看了一些文章,发现onChildAdded()其实是一个回调方法。为什么它不起作用?【参考方案2】:

它会打印数据,因为您的 ArrayList 正在被填充,但在您将其传递给适配器之后是异步的。

适配器持有对稍后通过 Firebase 回调填充的相同 ArrayList 的引用,但当数组中有新数据时,适配器本身需要使用 notifyDataSetChanged() 通知,否则它不会检查它。

基本上,每次从 Firebase 获取新数据时,您都需要找到一种方法来通知适配器数据集发生变化。一个简单的使用机制是callback。

【讨论】:

谢谢。但是 onChildAdded() 是我使用的回调方法。为什么它不起作用? 我在答案的后半部分进行了解释。在使用空的 ArrayList 初始化适配器后,回调会返回。回调返回后适配器不知道还有更多数据,这就是数据没有显示在屏幕上的原因。 使用回调尝试了很多次,但仍然无法实现。你能更具体地描述一下吗? ***.com/a/47853774/4380236 我认为这个答案描述得很好 成功实现。非常感谢!

以上是关于如何在 Android 中使用 MVC 模式从 firebase 检索数据? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Android 设计模式对比

Android 中 MVC、MVP 和 MVVM 对比

框架模式MVC与MVP在Android中的应用

如何实现自己的Android MVP框架

小试Android中使用MVC框架模式

Android - 框架之MVP模式的使用