天天看点

安卓——Activity的生命周期安卓的Activity活动栈安卓Activity的活动状态Activity活动状态切换触发回调方法代码:PS:手机的横竖屏转换时的问题

安卓的Activity活动栈

多个安卓Activity中的先后次序问题,需要用活动栈机制

安卓——Activity的生命周期安卓的Activity活动栈安卓Activity的活动状态Activity活动状态切换触发回调方法代码:PS:手机的横竖屏转换时的问题

如图:

  1. 每当新打开一个Activity时,会入栈,此时只有这个Activity是活动状态
  2. 除了栈顶的Activity其余的都处于暂停或者停止状态
  3. 如果内存不足,需要杀死Activity时,会释放资源使Activity处于非活动状态

安卓Activity的活动状态

分为四种:

  1. 活动状态:在活动栈处于栈顶的Activity,能被用户看到且可以交互,简单来说就是屏幕当前的Activity
  2. 暂停状态:当前Activity被部分遮挡,不再处于活动栈栈顶,并且无法交互。这里的部分遮挡是要被Activity遮挡,弹出框之类的不算被遮挡
  3. 停止状态:当前Activity被完全遮挡。比如按下HOME键或者跳转到别的页面
  4. 非活动状态:不是上面三种状态的Activity,例如被销毁的Activity

Activity活动状态切换触发回调方法

安卓——Activity的生命周期安卓的Activity活动栈安卓Activity的活动状态Activity活动状态切换触发回调方法代码:PS:手机的横竖屏转换时的问题

如图,转化过程如下:

  1. 当Activity生成时调用onCreate、onStart、onResume(相当于可以交互了),之后Activity开始运行
  2. 如果Acttvity处于暂停状态,会调用onPause
  3. Acitivty重新可以交互时调用onResume
  4. Activity变成停止状态,调用onPause和onStop
  5. Activity从停止状态变成活动状态,会调用onRestart和onStart和onResume方法
  6. 当前Activity从活动状态直接被销毁依次调用onPause、onStop、onDestory
  7. 当Activity处于暂停状态或者停止状态时,如果内存不足需要杀死Activty,进程终止,再打开需要重新生成

代码:

package net.onest.activitych0402;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    private EditText etMsg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("MainActivity","onCreate");
        etMsg = findViewById(R.id.et_msg);
        if (null != savedInstanceState){
            Log.e("onCreate",savedInstanceState.getString("msg"));
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e("MainActivity","onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e("MainActivity","onRestart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("MainActivity","onResume");
        //将数据进行恢复(读取文件,查询数据库等)
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e("MainActivity","onPause");
        //将页面的用户数据进行保存(文件、数据库中)
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e("MainActivity","onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("MainActivity","onDestroy");
    }

    public void buttonClicked(View view) {
        switch (view.getId()){
            case R.id.btn_dialog:
                Intent intent = new Intent();
                intent.setClass(MainActivity.this,
                        DialogActivity.class);
                startActivity(intent);
                break;
            case R.id.btn_new:
                Intent intent1 = new Intent();
                intent1.setClass(MainActivity.this,
                        NewActivity.class);
                startActivity(intent1);
//                finish();
                break;
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.e("MainActivity","onSaveInstanceState");
        super.onSaveInstanceState(outState);
        //保存用户数据
        outState.putString("msg",etMsg.getText().toString());
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        Log.e("MainActivity","onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
        //恢复用户数据
        String content = savedInstanceState.getString("msg");
        //显示到界面
        etMsg.setText(content);
    }
}

           

PS:

1. 如果想处于暂停状态,需要一个Activity覆盖到当前的Activity上面,并且不是完全覆盖,操作如下:

在资源目录下的values的styles.xml文件中,写一个样式,例如:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
	// 这里item是定义自己独特的地方的标签,我们需简要吧windowIsFloating设置为true
    <style name="DialogActivity" parent="AppTheme">
        <item name="android:windowIsFloating">true</item>
    </style>

</resources>
           

在manifests中设置activity的样式

<activity
            android:name=".DialogActivity"
            android:theme="@style/DialogActivity" /> <!--此处样式改成上面写好的那个-->
           

跳转到这样生成的Activity上,原来的就会处于暂停状态

2.

在返回时使用finish方法结束当前Activity,而不是去跳转回原来的Activity,

如果跳转回去就会产生两个不一样的Activity

// 比如我从MainActivity跳转到NewActivity
	Intent intent = new Intent();
	intent.setClass(MainActivity.this,NewActivity.class);
	startActivity(intent);
	// 如果在NewActivity中使用finish方法就会回到MainActivity中,并且只有一个
	// 如果用下面的这种方法,会产生两个MainActivity,假如第一个Activity中已经写好部分信息,跳转回去产生新的MainActivity中不会有那部分信息 
    Intent intent = new Intent();
    intent.setClass(NewActivity.this,MainActivity.class);
    startActivity(intent);	
           

3.ToolBar工具栏

我们需要在XML中先设置一个样式=>没有ActivityBar的样式

资源位置还在刚才的styles.xml文件中写

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> => 此处parent为重点
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
           

然后在布局中添加一个ToolBar(需要有这个的布局中写)

<androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:title="新的Activity"
        app:navigationIcon="@drawable/back"/> => 这个地方设置返回按钮
           

最后在java代码中替换掉ActivityBar

Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar); // 找到组件
	toolbar.setTitle("ToolBarDemo"); // 设置标题
	setSupportActionBar(toolbar); // 替换
           

手机的横竖屏转换时的问题

当横竖屏转换时,会将原来的Activity销毁,产生一个新的Activity,导致的问题是原来写好的内容没了。

此时有两种方法可以解决:

  1. 借助onPause和onRestart方法将数据存到文本或者数据库中
  2. 借助两个回调方法临时保持状态(第一个方法也是两个回调方法,不是那两个)

第二种的实现方式为重写onSaveInstanceState和onRestoreInstanceState方法,两个方法都有参数Bundle,借助于Bundle存键值对即可,例如:

@Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.e("MainActivity","onSaveInstanceState");
        super.onSaveInstanceState(outState);
        //保存用户数据
        outState.putString("msg",etMsg.getText().toString());
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        Log.e("MainActivity","onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
        //恢复用户数据
        String content = savedInstanceState.getString("msg");
        //显示到界面
        etMsg.setText(content);
    }
           

PS:onCreate的参数Bundle和这两个回调方法的Bundle是同一个对象