在火力地堡监听器设置辛格尔顿属性值地堡、监听器、火力、格尔

2023-09-05 04:42:22 作者:君子藏器于身`帶之而渡

我目前正在测试出火力地堡还有一个Singleton模式,我打算在整个应用程序的生命周期期间使用访问。我现在坚持的东西,看来真的是微不足道的,但我不能弄明白了我的生活。我的模型我使用了一个示例:书签在火力

I'm currently testing out Firebase along with a Singleton model I plan to use to access during the lifecycle of the whole app. I'm now stuck with something that seems really trivial but I can't figure it out for the life of me. I have a sample of the model I use: Bookmarks in firebase.

public class BookSingleton {



private static BookSingleton model;

private ArrayList<BookMark> bookmarks = new ArrayList<BookMark>();


public static BookSingleton getModel()
{
    if (model == null)
    {
        throw new IllegalStateException("The model has not been initialised yet.");
    }

    return model;
}


public ArrayList<Bookmark> theBookmarkList()
{
    return this.bookmarks;
}


public void setBookmarks(ArrayList<Bookmark> bookmarks){
    this.bookmarks = bookmarks;
}


public void loadModelWithDataFromFirebase(){
    Firebase db = new Firebase(//url);
    Firebase bookmarksRef = fb.child(//access correct child);


    final ArrayList<Bookmark> loadedBookmarks = new ArrayList<Bookmark>();
    bookmarksRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
                    //getting all properties from firebase...
                    Bookmark bookmark = new Bookmark(//properties here);
                    loadedBookmarks.add(bookmark);



                }
            }
            //bookmarks still exist here at this point
            setBookmarks(loadedBookmarks);

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });
    //by now loadedBookmarks is empty
    //this is probably the issue?
    //even without this line bookmarks is still not set in mainactivity
    setBookmarks(loadedBookmarks);
}

现在,当我开始mainActivity与辛格尔顿的实例设置我得到一个空的错误,因为明确的功能我写的负荷火力组没有模型数据。

Now when I start the mainActivity with the instance of the Singleton set I get a null error because clearly the function I wrote to load the model data from firebase sets nothing.

事情是这样的: MainActivity

Something like this: MainActivity

public class MainActivity extends AppCompatActivity {

private BookSingleton theModel;



@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // Load the model
    theModel = BookSingleton.getModel(this);
      //manually setting this works 
      //        ArrayList<Book> bookSamples = new ArrayList<Book>;
      //        bookSamples.add(aBookSample);

    theModel.loadModelWithSampleData(bookSamples);
    //should have set the singleton model property Bookmarks to the results from firebase

    theModel.loadModelWithDataFromFirebase();
    //returns 0
    Log.d(TAG, "" + theModel.theBookmarkList().size());


    setContentView(R.layout.activity_main);

    //......rest of code

任何指针将大大AP preciated。我有点新的与火力地堡,所以我真的不知道为什么,我期望它不起作用。

Any pointers would be greatly appreciated. I'm kinda new with Firebase so I'm not really sure why this doesn't work as I expect it to.

谢谢!

推荐答案

火力地堡的负载和数据同步的异步。所以,你的 loadModelWithDataFromFire​​base()不等待加载完成,它只是启动加载从数据库中的数据。到时候你的 loadModelWithDataFromFire​​base()函数返回时,装载还没有完成。

Firebase loads and synchronizes data asynchronously. So your loadModelWithDataFromFirebase() doesn't wait for the loading to finish, it just starts loading the data from the database. By the time your loadModelWithDataFromFirebase() function returns, the loading hasn't finished yet.

您可以轻松地与一些占尽天时地利的日志报表检验自己这一点:

You can easily test this for yourself with some well-placed log statements:

public void loadModelWithDataFromFirebase(){
    Firebase db = new Firebase(//url);
    Firebase bookmarksRef = fb.child(//access correct child);

    Log.v("Async101", "Start loading bookmarks");
    final ArrayList<Bookmark> loadedBookmarks = new ArrayList<Bookmark>();
    bookmarksRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.v("Async101", "Done loading bookmarks");
            //getting all properties from firebase...
            Bookmark bookmark = new Bookmark(//properties here);
            loadedBookmarks.add(bookmark);
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) { }
    });
    Log.v("Async101", "Returning loaded bookmarks");
    setBookmarks(loadedBookmarks);
}

相反,你可能期望,日志语句的顺序将是:

Contrary to what you likely expect, the order of the log statements will be:

Start loading bookmarks
Returning loaded bookmarks
Done loading bookmarks

您有两个选择来处理这种负载的异步特性:

You have two choice for dealing with the asynchronous nature of this loading:

壁球异步错误(通常伴随着喃喃自语的短语,如:这是一个错误,这些人不知道自己在做什么)

squash the asynchronous bug (usually accompanied by muttering of phrases like: "it was a mistake, these people don't know what they're doing")

拥抱异步兽(通常伴随着相当长的一段时间诅咒的,但同时通过和平和更好的表现后应用)

embrace the asynchronous beast (usually accompanied by quite some hours of cursing, but after a while by peace and better behaved applications)

如果你觉得捡了第一种选择,很好地同步原语将这样的伎俩:

Take the blue pill - make the asynchronous call behave synchronously

If you feel like picking the first option, a well placed synchronization primitive will do the trick:

public void loadModelWithDataFromFirebase() throws InterruptedException {
    Firebase db = new Firebase(//url);
    Firebase bookmarksRef = fb.child(//access correct child);

    Semaphore semaphore = new Semaphore(0);

    final ArrayList<Bookmark> loadedBookmarks = new ArrayList<Bookmark>();
    bookmarksRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Bookmark bookmark = new Bookmark(//properties here);
            loadedBookmarks.add(bookmark);
            semaphore.release();
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) { }
    });
    semaphore.acquire();
    setBookmarks(loadedBookmarks);
}

以红色药丸 - 处理数据同步的火力地堡的异步特性

19年12月和20年1月份在厂子辛劳,开始在股市火力全开

如果您而是选择拥抱异步编程,你应该重新考虑您的应用程序的逻辑。

Take the red pill - deal with the asynchronous nature of data synchronization in Firebase

If you instead choose to embrace asynchronous programming, you should rethink your application's logic.

您现在有先加载书签,然后装入样本数据。然后加载,甚至更多。

You currently have "First load the bookmarks. Then load the sample data. And then load even more."

使用异步加载模型,你应该这样想:每当书签已加载,我要加载的样本数据。当样本数据加载,我想要加载,甚至更多。这样的想法的好处是,它也可以当数据是可以改变的,因此同步多次:每当书签改变,我想也装载样品数据时,只要样本数据的变化,我想装载更多。 。

With an asynchronous loading model, you should think like "Whenever the bookmarks have loaded, I want to load the sample data. Whenever the sample data has loaded, I want to load even more." The bonus of thinking this way is that it also works when the data can be changed and thus synchronized multiple times: "Whenever the bookmarks change, I want to also load the sample data. Whenever the sample data changes, I want to load even more."

在code,这导致嵌套调用或事件链:

In code, this leads to nested calls or event chains:

public void synchronizeBookmarks(){
    Firebase db = new Firebase(//url);
    Firebase bookmarksRef = fb.child(//access correct child);

    final ArrayList<Bookmark> loadedBookmarks = new ArrayList<Bookmark>();
    bookmarksRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Bookmark bookmark = new Bookmark(//properties here);
            loadedBookmarks.add(bookmark);
            setBookmarks(loadedBookmarks);
            loadSampleData();
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) { }
    });
}

在上面的code,我们不只是等待一个值时,我们不是对付他们。这意味着只要书签被改变,在 onDataChange 被执行,我们(重新)加载样本数据(或任何其他行动适合您的应用程序的需要)。

In the above code we don't just wait for a single value event, we instead deal with all of them. This means that whenever the bookmarks are changed, the onDataChange is executed and we (re)load the sample data (or whatever other action fits your application's needs).