【问题标题】:Firebase Scalability - Query DB vs Custom Object ArrayList?Firebase 可扩展性 - 查询数据库与自定义对象 ArrayList?
【发布时间】:2018-02-08 15:51:52
【问题描述】:

我不确定我是否正确理解了某些文献。 Android 文档说不要创建不必要的对象。这篇文章 (Are Firebase queries scalable) 提到了 DB 查询的可扩展性是可以的,但我也读过将您的 Query 存储到 ArrayList 并通过它进行搜索而不是查询大型 DB 更好。

在我的情况下,我正在使用适用于 Android 的 Firebase 实时数据库,我想知道我是否得到了一个可能有 200 个示例/子节点的子节点,我是否应该将这些快照中的每一个放入模型类中,然后添加每个那些可以在 RecyclerView 中显示的 ArrayList?还是应该在字段上运行 .getValue() 并以其他方式存储它们?

我特别想查看与雇主关联的公司 ID,然后转到公司节点并获取该雇主的公司名称和商业城市

数据库:

这是我在活动中的代码部分:

companiesRef.addValueEventListener(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                for (DataSnapshot ds: dataSnapshot.getChildren()) {

                                    Log.i("companiesSnap", ds.toString());
                                    Log.i("KEYs", ds.getKey());
                                    companyIDKey = ds.getKey();
                                    //For each company ID in the Arraylist
                                    for (int i = 0; i < myCompanyIDsList.size(); i++) {
                                        //IF the IDs in arraylist from employee matches CompanyID from Companies node
                                        if(myCompanyIDsList.get(i).equals(companyIDKey)) {
                                            //IF THE ID matches, then get the associated company info
                                            Log.i("city", ds.child("businessCity").getValue().toString());
                                            Log.i("name", ds.child("businessName").getValue().toString());
                                            Businesses business = new Businesses(ds);
                                            myBusinessListItems.add(business);
                                            mAdapter.updateDataSet(myBusinessListItems);
                                        }
                                    }

整个班级:

public class BusinessesActivity extends Activity {

    private Context mContext;
    LinearLayout mLinearLayout;
    private RecyclerView mRecyclerView;
    private MyAdapterBusiness mAdapter = new MyAdapterBusiness(this);
    private RecyclerView.LayoutManager mLayoutManager;
    ArrayList<Businesses> myBusinessListItems;
    ArrayList<String> myCompanyIDsList;
    DatabaseReference employeesRefID, companiesRef;
    FirebaseDatabase database;

    String currentUser, companyIDKey;

    TextView getData;


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


        //RECYCLERVIEW STUFF
        mRecyclerView = (RecyclerView) findViewById(R.id.b_recycler_view);

        mContext = getApplicationContext(); // Get the application context

        // Define a layout for RecyclerView
        mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false);        //mLayoutManager = new LinearLayoutManager(mContext);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // Initialize a new instance of RecyclerView Adapter instance
        mRecyclerView.setAdapter(mAdapter);

        //ARRAY List to Store EACH Company ID
        myCompanyIDsList = new ArrayList<String>();

        myBusinessListItems = new ArrayList<Businesses>();
        currentUser =
                FirebaseAuth.getInstance().getCurrentUser().getUid();

        database = FirebaseDatabase.getInstance();

        getData = (TextView) findViewById(R.id.getData);

        companiesRef = database.getReference("Companies").child("CompanyIDs");


        final DataSnapshotCallback callback = new DataSnapshotCallback() {
            @Override
            public void gotDataSnapshot(DataSnapshot snapshot) {
                EmployeeUser employee = new EmployeeUser(snapshot);


                //myCompanyIDsList.add(employee);

                try {
                    for (DataSnapshot ds : snapshot.getChildren()) {
                        //WITHIN each UserId check the PushID
                        Log.i("TAG", "checkIfIDExists: datasnapshot: " + ds);

                        myCompanyIDsList.add(ds.getValue(EmployeeUser.class).getID());
                        Log.i("arrayList", myCompanyIDsList.toString());

                        //}
                    }

                    //GO THROUGH EACH COMPANY ID AND FIND INFORMATION
                        companiesRef.addValueEventListener(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                for (DataSnapshot ds: dataSnapshot.getChildren()) {

                                    Log.i("companiesSnap", ds.toString());
                                    Log.i("KEYs", ds.getKey());
                                    companyIDKey = ds.getKey();
                                    //For each company ID in the Arraylist
                                    for (int i = 0; i < myCompanyIDsList.size(); i++) {
                                        //IF the IDs in arraylist from employee matches CompanyID from Companies node
                                        if(myCompanyIDsList.get(i).equals(companyIDKey)) {
                                            //IF THE ID matches, then get the associated company info
                                            Log.i("city", ds.child("businessCity").getValue().toString());
                                            Log.i("name", ds.child("businessName").getValue().toString());
                                            Businesses business = new Businesses(ds);
                                            myBusinessListItems.add(business);
                                            mAdapter.updateDataSet(myBusinessListItems);
                                        }
                                    }


                                    }

                                }
                            @Override
                            public void onCancelled(DatabaseError databaseError) {
                                Log.d("Cancelled", databaseError.toString());
                            }

                        }); //END COMPANIES EVENT LISTENER

                    //} //END FOR
                }  //END TRY

                catch (Exception e) {
                    Log.i("FNull?", e.toString());
                }

                //mAdapter.updateDataSet(myListItems);
            }
        };


        getData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                employeesRefID = database.getReference("Employees").child(currentUser).child("Companies"); //SEE HOW ADD EMPLOYEES checks
                employeesRefID.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {

                        callback.gotDataSnapshot(dataSnapshot);
                    }


                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        Log.d("Cancelled", databaseError.toString());
                    }

                }); //END EMPLOYEE EVENT LISTENER
                Log.i("OutsideEvent", myCompanyIDsList.toString());

            }
        }); //END ONCLICK
        Log.i("OutsideonClick", myCompanyIDsList.toString());
    }


    interface DataSnapshotCallback {
        void gotDataSnapshot(DataSnapshot snapshot);
    }
}

【问题讨论】:

  • “我应该在字段上运行 .getValue() 并以其他方式存储它们吗?”其他方式也会使用内存。除非它使用的内存少于您的自定义类,否则您将一无所获。

标签: java android firebase firebase-realtime-database android-recyclerview


【解决方案1】:

使用 Firebase 时减少内存使用的技巧是仅加载您要向用户显示的数据。

如果您需要仅包含企业名称的列表,请在数据库中创建一个仅包含企业名称的节点并显示它。这样一来,您就减少了使用的带宽和内存,因为您没有加载公司的其他属性。

您通常会有一个“主列表”,其中包含每家公司(或其他实体类型)的所有属性。然后您可能有一个或多个“显示列表”,其中仅包含您需要在某些区域显示的业务信息。这种重复数据在 NoSQL 数据库中很常见,称为非规范化。

如需更好的介绍,请阅读Denormalizing Your Data is NormalNoSQL data modeling,并观看Firebase for SQL developers

【讨论】:

  • 感谢弗兰克,它开始融合了。几个问题:那么您是否暗示只要您以最佳方式构造它(并且比将许多快照下载到 ArrayList 中更好),多次查询 FirebaseDB 就可以了吗?另外,在我的示例中,我会从公司节点中删除“EmployeeIDs”和“ModeratorIDs”吗?感谢 youtube 系列,因为我确实来自 SQL 背景,并且在过去一周一直致力于非规范化我的 Firebase DB。
猜你喜欢
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-08
相关资源
最近更新 更多