看了《第二行代码》一段时间了,这次按照书上的内容,用广播写个退出登录的功能。强制下线功能会关闭掉所有的活动,然后回到登录界面。
先新建一个空项目day10_BroadcastBestPractice
一、管理页
新建一个ActivityCollector
类,用来管理所有的活动
public class ActivityCollector {
private static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for (Activity activity : activities){
if (!activity.isFinishing()){
activity.finish();
}
}
activities.clear();
}
}
新建一个BaseActivity
活动当所有活动的父类
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
最后在AndroidManifest.xml
把登录页设置为启动页:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.day10_broadcastbestpratice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaseActivity" />
<activity android:name=".MainActivity"></activity>
</application>
</manifest>
二、登录页
新建LoginActivity
,对应的布局文件activity_login.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<TextView
android:gravity="center"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="用户名:"/>
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:id="@+id/account"
android:hint="在这里输入用户名啊~魂淡~"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:text="密码:"
android:textSize="18sp"/>
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/password"
android:inputType="textPassword"
android:layout_gravity="center_vertical"
android:hint="在这里输入密码啊~魂淡~"/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="登录"
android:id="@+id/login"/>
</LinearLayout>
这是它的LoginActivity
,账号和密码已经锁死:
public class LoginActivity extends BaseActivity {
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
accountEdit = findViewById(R.id.account);
passwordEdit = findViewById(R.id.password);
login = findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
if (account.equals("breathy") && password.equals("000000")){
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this, "账号或密码不正确", Toast.LENGTH_LONG).show();
}
}
});
}
}
三、主页
主页就是登录成功的页面,来康康他的布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="恭喜你登陆成功!"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="点我注销"
android:id="@+id/force_offline"/>
</FrameLayout>
主活动的下线按钮会发送出OKForceOffline
这样一条广播
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button force_offline = findViewById(R.id.force_offline);
force_offline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("OKForceOfflineReceiver");
sendBroadcast(intent);
}
});
}
}
四、广播接收器
为了使得强制下线功能不依附于任何界面,但是可以在任何时候都能弹出对话框阻塞操作,所以这个动态广播接收器应该在BaseActivity
中,要点如下:
- 完成广播接收器的注册。为了保证其能接收到下线的消息,接收广播的活动必须处于栈顶,即
onResume()
下 - 响应广播的功能。弹出一个不可取消的对话框,提示下线
- 注销广播接收器情况。为了避免重复注册广播接收器,在
onPause()
里注销广播接收器
代码如下:
public class BaseActivity extends AppCompatActivity {
private ForceOfflineReceiver receiver;
@Override
protected void onPause() {
super.onPause();
if (receiver != null){
unregisterReceiver(receiver);
receiver = null;
}
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("OKForceOfflineReceiver");
receiver = new ForceOfflineReceiver();
registerReceiver(receiver, intentFilter);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
class ForceOfflineReceiver extends BroadcastReceiver{
@Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("提示");
builder.setMessage("你被踢下线了。");
builder.setCancelable(false);
builder.setPositiveButton("行吧", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.finishAll();
Intent i = new Intent(context, LoginActivity.class);
context.startActivity(i);
}
});
builder.show();
}
}
}
五、运行
完美!