安卓:注销时清除所有活动的完美方法?

8

我的应用程序中所有的活动都有注销按钮,用户可以从任何活动注销。我想在不显示上一个活动的情况下将用户发送到登录活动。为此,我使用以下方法:

以下是注销方法删除会话

public void logoutUser() {
    //clearing all data from sharedPreferences
    editor.clear();
    editor.commit();
    Intent intnt = new Intent(contxt, LoginActivity.class);
    // Closing all the Activities
    intnt.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    // Add new Flag to start new Activity
    intnt.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
    // Staring Login Activity
     contxt.startActivity(intnt);

}

当用户在第二个活动中单击注销按钮时,将调用注销方法。我的第二个活动类继承自SherlockFragmentActivity。

public void Logout(MenuItem v) {
    sessionMngr.logoutUser();
}

当我按下注销按钮时,我会进入登录界面,但是当我按下设备上的返回按钮时,它会显示以前的活动 - 当我在登录界面按下返回按钮时,我应该进入Android主屏幕。
我在stackoverflow上看到了一些问题,但没有实现我的目标。有人告诉我在清单文件中使用android:noHistory="true",但是当我在第三个活动中并按下返回按钮时,它会显示Android主屏幕,但它应该进入第二个活动。我还尝试了FLAG_ACTIVITY_NO_HISTORY,但这也没有实现我的目标。
我不明白我错在哪里。请问有没有解决方案。
提前感谢。
11个回答

14

尝试同时指定这两者:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

为了保险起见,在启动这个活动后调用finish()。


Intent.FLAG_ACTIVITY_CLEAR_TASK 这个字段需要API级别11。 我已经使用了FLAG_ACTIVITY_NEW_TASK。请参见上面的代码。 - nilesh wani
新任务不足以清除历史记录,抱歉没有注意到它不能在API 11下使用。我无法帮助你。 - Chor Wai Chun
@nileshwani 经过对我的上一个项目的一番搜索,我发现以前我在每个活动中都分配了广播监听器,因此每当我打开需要成为新任务的东西时,我发送广播,它们将调用finish()。 - Chor Wai Chun

10

最好的方法是在您的应用程序中使用LocalBroadcastManager进行注销。

当用户按下注销按钮时,您可以使用以下代码发送本地广播。

@Override
public void onclick(View view){

  //do this on logout button click
  final String LOG_OUT = "event_logout";
  Intent intent = new Intent(LOG_OUT);
  //send the broadcast to all activities who are listening
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
现在所有的活动都应该监听这个广播。而这个活动将会变成:
@Override 
    protected void onCreate(Bundle savedInstanceState) {

  // Register mMessageReceiver to receive messages.
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter(LOG_OUT));
}

// handler for received Intents for logout event 
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
      //do your code snippet here.
      finish();
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is not visible
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

注意:如果您有多个活动,则建议从基础活动扩展所有活动,并仅在基础活动中实现此本地广播管理器。这样,您只需在一个位置实现注销代码。


1
不错的解决方案,只需从this.finish()中删除这个部分,因为它没有引用activity。 - Jumpa

4
这是我解决它的方法:
Intent intent = new Intent(context, ActivityLogin.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

适用于API版本>=11


2
Intent intent = new Intent(SourceActivity.this,DestinationActivity.class); 
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

在转到登录界面或任何目标界面之前,使用此代码。这样,堆栈中的所有活动都将被清除。

希望这能对您有所帮助。


1
"

finishAffinity() 在 API 级别 16+ 上表现非常出色。

"

0

我希望这可以帮到你。

1) 我使用了Builder来在用户点击注销按钮后显示一个消息。

2) 一旦用户点击“带我走! ”,它将返回到主页面,当您按下设备上的返回按钮时,它不会显示之前的活动。

logout=(Button)findViewById(R.id.btn_logout);

        logout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    final AlertDialog.Builder builder = new AlertDialog.Builder(EngagementActivity.this);
                    builder.setTitle("Info");
                    builder.setMessage("Do you want to logout ??");
                    builder.setPositiveButton("Take me away!", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            Intent intent = new Intent(EngagementActivity.this,MainActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivity(intent);

                            finish();

                        }
                    });

                    builder.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            dialogInterface.dismiss();
                        }
                    });

                    AlertDialog dialog = builder.create();
                    dialog.show();
                }
            });

0

尝试使用FLAG_ACTIVITY_MULTIPLE_TASK进行测试

如果您现在已经拥有它,它应该可以正常工作,登录活动是根(启动器)活动吗?

您可以尝试在onResume方法中执行以下操作

if(!login) {
    finish();
}

看起来不太好看,但应该能正常工作。


0

在您的LoginActivity中,您可以使用onBackPressed来定义在按下返回键时它必须执行什么操作。

@Override
public void onBackPressed() {
//what it should do on back
}

0
在您的活动中,当用户单击注销按钮时
   Button logout = (Button) findViewById(R.id.logout);
   logout.setOnClickListener(new OnClickListener()
   {
    Intent myIntent = new Intent(CurrentActivity.this, LoginActivity.class);
    myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);// clear back stack
    startActivity(myIntent);
    finish();
   });

在 LoginActivity 中点击返回按钮。如果 LoginActivity 是 MainActivity,则在按钮点击时完成该活动并转到主屏幕。

以上代码有什么问题,它与你的代码类似,只是我写了一个名为“Logout”的onclick事件。我无法调用finish方法,因为这不是活动类。 - nilesh wani
当您完成当前活动并从后退堆栈中弹出时,将显示后退堆栈中的上一个活动。由于后退堆栈已被清除,因此它将导航到 LoginActivity。 - Raghunandan
还有一个调用finish()的上下文,例如((Activity) context).finish(); - Raghunandan
当我写 ((Activity) context).finish() 时,它遇到了 ClassCastException 异常。 - nilesh wani
https://dev59.com/AmTVa4cB1Zd3GeqP_ARA - Raghunandan
将上下文传递给非活动类的构造函数,使用它来启动意图并调用finish()。 - Raghunandan

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接