在除活动之外的另一个类中使用 Firebase 需要重复调​​用

Posted

技术标签:

【中文标题】在除活动之外的另一个类中使用 Firebase 需要重复调​​用【英文标题】:Using Firebase in another class except activity requires duplicate calls 【发布时间】:2014-06-16 12:13:24 【问题描述】:

我正在尝试使用 android 应用程序实现 Firebase,并且我编写了一个简单的登录代码。问题是除非在 Activity 类中使​​用 Firebase 代码,否则用户需要按两次登录按钮。

简而言之,用户尝试登录,但 Firebase 引用并未立即检索,因此返回错误结果。但是,几秒钟后,您可以看到 LogCat 返回了一个真实的结果,如果用户再次单击登录按钮,他/她就可以登录了。

LogCat

04-30 10:29:25.003: I/WMT(30932): activity
04-30 10:29:25.003: I/WMT(30932): controller
04-30 10:29:25.003: I/kolla(30932): https://REMOVEDURL.firebaseio.com/users/testing
04-30 10:29:25.003: I/kolla(30932): ITS TRUE!
04-30 10:29:25.133: D/dalvikvm(30932): GC_CONCURRENT freed 514K, 14% free 9799K/11271K, paused 6ms+13ms, total 62ms
04-30 10:29:26.274: I/kolla(30932): datachange
04-30 10:29:26.274: I/kolla(30932): https://REMOVEDURL.firebaseio.com/users/testing
04-30 10:29:26.274: I/kolla(30932): hej
04-30 10:29:26.274: I/kolla(30932): Normal password: hej
04-30 10:29:26.274: I/kolla(30932): Password is correct
04-30 10:29:26.274: I/kolla(30932): userExists is true

调用活动

public class MainActivity extends Activity 

    private MainController mainController;

    private EditText edtUsername;
    private EditText edtPassword;

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

        mainController = new MainController();

        edtUsername = (EditText)findViewById(R.id.edtUsername);
        edtPassword = (EditText)findViewById(R.id.edtPassword);
    

    public void btnLoginClick(View view)
    
        Log.i("WMT", "activity");
        if(mainController.login(edtUsername.getText().toString(), edtP    assword.getText().toString()) != null) 
            Toast toast = Toast.makeText(getApplicationContext(), "Login correct, redirecting...", Toast.LENGTH_LONG);
            toast.show();

            User user = mainController.login(edtUsername.getText().toString(), edtPassword.getText().toString());

            Intent intent = new Intent(this, UserWindowActivity.class);
            intent.putExtra("user", user);
            startActivity(intent);
         else 
            Toast toast = Toast.makeText(getApplicationContext(), "Invalid username and/or password", Toast.LENGTH_SHORT);
            toast.show();
        
    

控制器

public final class MainController 

    // This controller handles main activity

    private FirebaseDba dba;

    public MainController() 
        dba = new FirebaseDba();
    

    public User login(String username, String password) 
        Log.i("WMT", "controller");
        return dba.login(username, password);
    


数据库访问类

public class FirebaseDba 

    private final String FIREBASE_URL = //Removed for safety purposes;

    private Firebase fb;

//  String savedPassword;
    boolean userExists;

    public FirebaseDba() 
        fb = new Firebase(FIREBASE_URL);
    

    private Firebase getFirebaseConnection() 
        return fb;
    

    public User login(final String username, final String password) 
        final Firebase dbaa = new Firebase(fb.toString() + "/users/" + username);
        Log.i("kolla", dbaa.toString());
        dbaa.addValueEventListener(new ValueEventListener() 
            @Override
            public void onDataChange(DataSnapshot snap) 
                Log.i("kolla" ,"datachange");
                Log.i("kolla", dbaa.toString());
                Object value = snap.getValue();
                if (value != null) 
                    String dbPassword = snap.child("password").getValue().toString();
                    Log.i("kolla", dbPassword);
                    Log.i("kolla", "Normal password: " + password);
                    if (password.equals(dbPassword)) 
                        Log.i("kolla", "Password is correct");
                        changeToTrue();
                        if(userExists) Log.i("kolla", "userExists is true");

                    
                
                else 
                    userExists = false;
                
            
            @Override
            public void onCancelled(FirebaseError arg0) 
                // TODO Auto-generated method stub

            
        );

        Log.i("kolla", "ITS TRUE!");
        if (userExists == true) 
            Log.i("kolla", "userExists equals true");
            return new User(username, password);
        

        //return new User(username, password);
        return null;
    

    public void changeToTrue() 
        userExists = true;
    

编辑:没有人遇到过这个问题吗?每个人都在他们的活动中运行他们的数据库访问吗?因为这听起来像是不好的做法,我想用一个单独的课程来解决这个问题。感谢所有帮助。

【问题讨论】:

【参考方案1】:

Firebase 事件不会像您的代码所期望的那样同步触发。当从服务器获取数据时它们会触发。您可以做的是将回调传递给您的 FirebaseDba.login 方法,当调用结果可用时调用该方法。您的登录调用不应返回用户,因为您无法保证您拥有数据。

您也可以考虑查看简单登录客户端 (https://www.firebase.com/docs/security/simple-login-java-overview.html) 来为您处理身份验证。或者如果没有,您至少可以查看它用来实现您想要的结果的代码:https://github.com/firebase/firebase-simple-login-java

【讨论】:

以上是关于在除活动之外的另一个类中使用 Firebase 需要重复调​​用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MainActivity 之外的另一个类中调用 findViewById(R.id.textView)?

Android:onResume() 正在跳转到除异常之外的另一个活动

TypeScript - 是不是有一个选项可以禁止在除布尔值之外的任何内容前面使用“!

如何使用 .htaccess 在除一个目录 /images 之外的所有 URL 上强制使用 HTTPS?

PHP:在除最后一个元素之外的每个元素之后显示逗号。使用“for”语句而不使用“内爆/爆炸”

如何在除 Localhost 之外的特定 IP 上运行 Geoserver?