【问题标题】:How do I implement an Observer to get data from a listener?如何实现观察者以从侦听器获取数据?
【发布时间】:2016-05-07 20:29:12
【问题描述】:

我正在使用MaterialDrawer 库为我的应用程序创建一个简单的抽屉,库中的一些类实例在调用时需要一个字符串传递给它们。一个例子是IProfile 类:

IProfile profile = new ProfileDrawerItem().withName("John Doe");

withName() 方法接收一个字符串。

我创建了一个类 MyObservable.java(扩展 Observable)类,我打算用它来获取要在我的 MainActivity 中使用的数据,该类实现了 MaterialDrawer 库。在这堂课中,我有一个方法implementData(),它有我的监听器来满足我从我的firebase数据库中需要的东西。

这就是它的样子:

    public class MyObservable extends Observable {

    // Attach our firebase reference...
    Firebase userRef = new Firebase("https://myApp.firebaseio.com/users");
    AuthData authData;

    public String username = "";
    public String email = "";


    public void changeUsername(String username) {
        this.username = username;

        setChanged();
        notifyObservers(username);
    }


    public void implementData(){
        // Get the authentication data of our user from the reference.
        authData = userRef.getAuth();

        // This is the listener I have to get the data from. 
        userRef.child(authData.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {

                UserSchema user = snapshot.getValue(UserSchema.class);
                // This guy needs to be used in the MainActivity appDrawer() method
                String userName = user.getName();
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });

    }
}

class MyObserver implements Observer {

    public void update(Observable observable, Object data) {
        // For now I just print it out to System.out
        System.out.println("Username:" + data);
    }
}

然后我使用changeUsername() 方法通知我的观察者用户名更改:

public void changeUsername(String username) {
        this.username = username;

        setChanged();
        notifyObservers(username);
    }

在 MyObservable 类中,我有一个 MyObserver 类,它实现 Observer 并在观察者更新时调用 update() 方法。在目前的update() 方法中,我只是打印出用户的username 以确保确实发生了一些事情。

这是我需要来自观察者的数据的地方(在 MainActivity 中):

public class MainActivity extends AppCompatActivity {
    ...

    public void appDrawer(){

        IProfile profile = new ProfileDrawerItem()

                // I need the user's data here
                .withName("Test")
                .withEmail("test@test.com")
                .withIcon(R.drawable.avatar2);
    }

    ...

}

我花了几个小时试图通过尝试检索要在我的 MainActivity 中使用的数据来对侦听器中发生的事件进行“反应”,但我不确定我是否正在使用 Observable/正确的观察者模式,因为这是 Firebase 获取数据的异步事件,所以使用观察者是最好的方法。

appDrawer() 方法在我的 Activity 的 onCreate() 中调用。

如何使用 Observer 从 Listener 检索数据,以便在其他地方使用它?

【问题讨论】:

    标签: java android firebase observer-pattern observable


    【解决方案1】:

    我无法通过你的设计来判断到底发生了什么。将一个类命名为 Listener 然后将其命名为 Observable 似乎违反直觉。听众聆听或观察。尽管如此,听起来你在Listener 中有另一个类是Observer,所以我有点迷茫,但你似乎不确定你是否正确地实现了模式。我可以举个例子来说明。

    public class MyObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            System.out.println(arg + " " + ((MyObservable)o).name);
        }
    }
    
    public class MyObservable extends Observable {
    
        public String name = "Observable";
    
        public void changeMe(String word) {
            setChanged();
            notifyObservers(word);
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            MyObservable myObservable = new MyObservable();
            myObservable.addObserver(new MyObserver());
            myObservable.changeMe("Hello");
        }
    }
    

    update 方法为您提供了您正在观察的对象以及您传递给notifyObservers() 的参数(您希望与观察者共享的数据)。如果你已经这样做了,那么你应该得到你期望的行为。

    如您所见,数据可以发送到可观察对象外部或内部的观察者。当你运行它时,输出是......

    Hello Observable

    【讨论】:

    • notifyObservers(String) 应该从 changeMe() 调用。
    • @cybergen,“应该”对我来说可能有点限制。它是公开的,所以它是故意暴露的。我会说,在一般情况下,在每个更改状态的方法中调用 notifyObservers 可能是过度的。不过我明白你的意思。在 OP 的情况下,这并不重要,因为只有一个通知。为了您的观看乐趣,我将对其进行编辑,以便更好地匹配 OP 的代码。
    • 哇,非常感谢,所以我可以让changeMe 方法返回正在更新的字符串,而不必在可观察对象中添加观察者是吗?跨度>
    • 我不完全确定我明白你的意思,因为你说返回,这里没有返回任何东西。如果您的意思是“返回”给观察者,那么是的。您可以通过将字符串传递给changeMe(),然后再传递给notifyObservers(),将其向上推。 @geek.x
    • @geek.x,如果您查看我的示例,您会发现 如何 将值提供给观察者并不重要。在您的示例中,您有一个通知观察者的方法 - 好! - 但你从不叫它。所以,当数据发生变化时,通知观察者。如果您需要您的主要活动立即更新视图,主要活动将需要是观察者,或者它需要一个观察者的实例,它将能够 大多数来自它的最新用户名或作为对它的引用传递,以便它可以更新视图(我认为:))。
    猜你喜欢
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    相关资源
    最近更新 更多