【问题标题】:App flow with AccountManagerAccountManager 的应用流程
【发布时间】:2013-08-14 18:17:37
【问题描述】:

我一直在为我的应用程序结构苦苦挣扎。而且看起来这种结构真的让我在开发其他功能时遇到了很多痛苦。所以在继续之前,我想得到一些建议,看看我是否在这里做错了什么。

我的应用程序的目的是连接到服务器,我使用 AccountManager 机制在设备上创建一个帐户并存储一个令牌,该令牌应该用于从服务器请求数据。在创建帐户时,一切都很好。 (它也可以从设备设置 -> 添加一个帐户)

事情是这样的:

MainActivity 是在您启动应用程序时检查您是否有帐户的 Activity。 如果您有帐户,我会在静态变量中获取令牌,以便 MainActivity 中的每个片段都可以访问它。 (应该工作,但没有) 否则,我使用 LoginActivity 创建一个意图以在设备上创建一个帐户。 问题是我的片段无法获取此令牌,因为当我使用 AccountManager.getAuthToken() 在线程中恢复令牌时,片段是在恢复此令牌之前创建的。因此我无法从我的服务器请求数据。

这让我觉得我的应用程序结构可能不是那么好。 所以我在想,“如果我喜欢这样呢?” :

  • 用户启动应用程序
  • MainActivity 就像一个引导程序,它检查帐户并在设备上有帐户时获取令牌,但不会像当前版本那样生成任何类型的视图。
  • MainActivity 或者重定向到 LoginActivity 或 ContentActivity(我们这样称呼它,应该使用我的令牌在我的 ListViews 中填充数据的活动)

这种方式让我认为 MainActivity 将有令牌通过,但我不确定它在 UX 方面是否理想。 (在访问内容之前必须等待令牌)。 在这一点上,我对每一个建议都持开放态度,因为我真的被困住了。

谢谢!

更新 1:

它更多的是登录/注册应用程序逻辑,而不是处理 AccountManager。我已经设法让它们工作了,但我真的在为“最佳实践”应用程序逻辑结构而苦苦挣扎,所以我不会因此而遇到许多其他问题(因为我真的没有时间)。 我所需要的只是一个图表或一些东西来向我展示一个“最佳实践”示例,以使我的应用程序按照我上面解释的方式工作。 我也遇到了一个问题,因为当我启动 MainActivity 时,它会检查一个帐户,如果没有,它会启动 LoginActivity,但如果我按下回,我可以看到 MainActivity(未填充)。

【问题讨论】:

    标签: android logic structure flow accountmanager


    【解决方案1】:

    更多的一般做法是你正在使用的:

    这种结构是完全可以接受的,是依赖于服务器的应用程序的正常流程。我更喜欢日志记录只是一个选项的模型,其中包含一些不需要登录的内容。每当触发需要登录的操作时,都会向用户显示登录信息。但是,您的模型应该可以正常工作。

    我看到你的问题是

    1. I also ran into a problem because when I start the MainActivity it checks for an account and if not it launches LoginActivity but if I press back, i can see MainActivity (unfilled).

      这个问题可以通过一个不可见的 Dispatch Activity 来解决,它根据当前用户的状态启动 MainActivity 或 LoginActivity。如图所示,只需finish() 您决定后的调度活动即可。您的 LoginActivity 负责重新启动 DispatchActivity,它将重新决定下一步。一般不要覆盖 LoginActivity 的 onBackPressed 来启动 Dispatch,只要登录成功就启动 Dispatch。

      但是,如果您决定在用户​​未登录的情况下在 Activity 中显示一些内容,您可以在登录请求后使用 onActivityResult 刷新 MainActivity 的内容。

    2. The problem is that my fragments can't get this token because, as i'm recovering the token in a thread using AccountManager.getAuthToken(), the fragments are created before this token is recovered.

      这个问题是正常的。如果您在处理登录请求时已经创建了活动/片段,则必须能够通知这些。基本上,如果您的片段不显示“未经身份验证”的内容,那么您不应该遇到这个问题,因为您甚至不应该在登录之前创建这些片段。

      但是,如果您决定在活动/片段中显示某些内容,即使用户未登录,您也必须通知这些正在运行的组件有关状态更改的信息。一种方法是在您的活动中实现 onResume 以检查用户是否已登录并进行适当的更改。另一种方法是使用本地广播通知正在运行的活动/片段状态已更改:

      BroadcastReceiver mReciever = new BroadcastReceiver() {
          public void onReceive(Context context, Intent intent) {
                  //do whatever you want //check state
          }
      };
      
      public void onCreate(Bundle state) {
         //bla bla
         //bla bla
         LocalBroadcastManager.getInstance(mContext).registerReceiver(mReciever, new IntentFilter("your_package_name.LOGIN_STATE_CHANGED"));
      }
      

      每当状态改变时,发送广播:

      Intent intent = new Intent("your_package_name.LOGIN_STATE_CHANGED");
      LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
      

    当然,这可能会因具体情况而异。例如,如果您检查Touch App on Google Play,您会注意到我创建了一个无论用户登录状态如何都可见的调度屏幕,然后在用户进入需要登录的活动时要求用户登录。在这种情况下,任何需要登录的活动都应该相应地实现其 onActivityResult 并在用户登录时更新用户界面,或者在用户未登录时完成。另一方面,psst app on Google Play 使用启动屏幕来根据用户的状态决定是进入登录屏幕还是主屏幕。

    【讨论】:

    • 查看了完全开源的 Last.fm 应用程序,他将这种调度直接发送到“登录”活动中。他实际上检查了很多东西(如意图操作),因为当用户来自“添加帐户”设置、用户配置应用小部件或刚启动应用时,会使用此活动。你认为这也是一个好方法吗? (这里是活动代码github.com/c99koder/lastfm-android/blob/master/app/src/fm/last/…的链接)我也想避免SplashScreen,因为我认为它对用户体验不利
    • 很好。是的。如果有人坚持,一个单一的活动可以用于一切。
    • 非常感谢,你真的帮了我这个忙!我现在设法让它工作。
    • 但是当您在整个应用程序中拥有多个进入各种活动的入口点时,此解决方案就不太适用了。也就是说,当 DispatchActivity 不是唯一可以启动以使用所需凭据的活动时。在这种情况下,建议的流程会失败。
    • @Ardoramor 实际上在这里我们认为 DispatchActivity 有一个输入,即用户是否登录。你可以添加额外的输入来帮助它决定下一步去哪里。
    【解决方案2】:

    示例代码..

    public class DispatchActivity extends ActionBarActivity {
    
    
        SharedPreferences prefs = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
    
            prefs = getSharedPreferences("me.sanath.megh", MODE_PRIVATE);
            boolean islogin = prefs.getBoolean("islogin",false);
            if(islogin)
            {
                Intent i = new Intent(this,homepageActivity.class);
                startActivity(i);
                finish();
            }else{
    
                Intent i = new Intent(this,LoginActivity.class);
                startActivityForResult(i,1);
            }
        }
    
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
            if (requestCode == 1) {
                boolean islogin = prefs.getBoolean("islogin",false);
                if(islogin)
                {
                    Intent i = new Intent(this,homepageActivity.class);
                    startActivity(i);
                    finish();
                }else{
    
                    Intent i = new Intent(this,LoginActivity.class);
                    startActivityForResult(i,1);
    
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-24
      • 2015-03-11
      • 2011-02-12
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多