Detailed explanation of Android's Activity activities

One or four components

1.1 The Activity component is a separate window, and the program flow must run in the Activity.

1.2 The service component is used to complete user-specified operations in the background.

1.3 The content provider component will prepare a content window for all applications and retain databases and files.

1.4 The broadcast receiver component is a mechanism for transferring information between programs, and its function is to receive or send notifications.

Two Activity Introduction

2.1 Activity is the most used of the four major components. It is the carrier of data display and the interface for user visual display and behavior control.

2.2 A program contains one or more activities, and the jump and data communication between activities depend on Intent (intent).

Three Activity creation

3.1 Activity is a Java class, first create a Class, inherit from Activity or

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

3.2 Create xml layout file

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

     ...................    

</FrameLayout>

3.3 Register the Activity component in the manifest file AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">
    <uses-permission android:name="android.permission.INTERNET" />
    <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/Theme.MyApplication">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

3.5 Intent startup component

Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

Four Context context

4.1 Many people who are new to Context do not understand what it is used for and what the context means. Context is actually an environment in which programs run. In this environment, four major components can be started, page jumps, and resource access can be performed. To sum up, it is the bridge between the application program and the system, and the interface for the application program to access various resources of the system

4.2 There are more than one type of Context. Although all of them can access system resources, their life cycles are different. Can be subdivided into the following three categories: Application, Activity, service

4.3 Comparison of life cycle

The life cycle of Application is the longest, and generally the application will always exist if it is not killed.

The life cycle of Activity and Service is relatively short, so most of the memory leaks occur on the references of these two Contexts

4.4 Comparison of Context Usage Scenarios

Five Activity life cycle

5.1 Life cycle diagram

5.2 Copy the life cycle of Activity as follows 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //当Activity第一次被创建的时候调用此方法.一般在此方法中进行控件的声明,添加事件等初始化工作.
    }

    @Override
    protected void onStart() {
        super.onStart();
        //当Activity被显示到屏幕上的时候调用此方法.
    }

    @Override
    protected void onResume() {
        super.onResume();
        //当此Activity能够被操作之前,也就是能够获得用户的焦点之前调用此方法.
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        //当Activity被停止后又被再次启动之前调用此方法.接着将调用onStart()方法.
    }

    @Override
    protected void onPause() {
        super.onPause();
        //当第一个Activity通过Intent启动第二个Activity的时候,将调用第一个Activity的onPause()方法.然后调用第二个Activity的onCreate(),onStart(),onResume()方法,接着调用第一个Activity的onStop()方法.如果Activity重新获得焦点,则将调用onResume()方法;如果此Activity进入用户不可见状态,那么将调用onStop()方法
    }

    @Override
    protected void onStop() {
        super.onStop();
        //当第一个Activity被第二个Activity完全覆盖,或者被销毁的时候回调用此方法.如果此Activity还会与用户进行交互,将调用onRestart方法();如果此Activity将被销毁,那么将调用onDestroy()方法.
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //Activity被销毁之前调用此方法.或者是调用finish()方法结束Activity的时候调用此方法.可以在此方法中进行收尾工作,比如释放资源等.
    }
}

5.3 For example, two Activities, AActivity.java and BActivity.java

Open AActivity, the life cycle is as follows:

AActivity onCreate() ->  AActivity onStart() -> AActivity onStart()

Jump from AActivity to BActivity, the life cycle is as follows:

AActivity onPause() -> BActivity oncreate() -> BActivity onstart() -> BActivity onresume() -> AActivity onstop()

Return AActivity from BActivity, the life cycle is as follows:

BActivity onPause() -> AActivity onRestart() -> AActivity onStart() -> AActivity onResume() -> BActivity onStop() -> BActivity onDestroy()

5.4 Activity startup mode

  • standard: The default startup mode. Every time the activity is activated, an activity instance is created and put into the task stack.
  • singleTop: If an Activity activates itself, that is, the top of the task stack is the Activity, it does not need to be created, and the Activity must be created in other cases.
  • singleTask: If the activity to be activated is in the task stack, there is no need to create it. You only need to put this Activity on the top of the stack, and pop all the Activity instances above this Activity out of the stack.
  • singleInstance: There is only one instance, and this instance runs independently in a task. This task has only this instance, and no other activities are allowed to exist.

 There are two ways to set the startup mode:

Static settings:

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">
	<activity
		android:name=".MainActivity"
		android:launchMode="standard"
		android:exported="true">
		<intent-filter>
			<action android:name="android.intent.action.MAIN" />

			<category android:name="android.intent.category.LAUNCHER" />
		</intent-filter>
	</activity>
	<activity android:name=".Activity2"
		android:launchMode="singleTop"/>

	<activity android:name=".Activity3"
		android:launchMode="singleTask"/>

	<activity android:name=".Activity4"
		android:launchMode="singleInstance"/>
</application>

Dynamic settings:

//默认不设置,即standard
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

//FLAG_ACTIVITY_SINGLE_TOP,即singleTop
Intent intent2 = new Intent(this,Activity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent2);

//FLAG_ACTIVITY_CLEAR_TOP,即singleTask
Intent intent3 = new Intent(this,Activity3.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent3);

//FLAG_ACTIVITY_NEW_TASK,即singleInstance
Intent intent4 = new Intent(this,Activity4.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent4);

Six Intent intent

6.1 As mentioned above, Intent is also very important. It is a bridge connecting components and used to start communication between activity, service and broadcast receiver and components. Content Provider itself is a communication mechanism and does not need to pass Intent.

6.2 Intent startup component

  • Use Context.startActivity() or Activity.startActivityForResult(), passing in an intent to start an activity. Use Activity.setResult(), passing in an intent to return the result from the activity.
  • Pass the intent object to Context.startService() to start a service or send a message to a running service. Pass the intent object to Context.bindService() to bind a service.
  • Pass the intent object to broadcast methods such as Context.sendBroadcast(), Context.sendOrderedBroadcast(), or Context.sendStickyBroadcast(), and they will be passed to the broadcast receiver

6.3 Properties of Intent

  • component (component): the purpose component, generally the full path of the class name (package name. class name)
  • action: action used to express intent
  • category (category): the category used to represent the action
  • data (data): indicates the data to be manipulated by the action
  • type (data type): description of the data type
  • extras (extended information): extended information
  • Flags (flag bits): expect the mode of operation of this intent

According to different attribute settings, start Activity is divided into explicit and implicit:

  • Explicit means to start directly, clearly pointing to an Activity class component.
  • Implicit refers to indirect startup, and finds matching components based on action, category, data, etc.

6.4 Three ways to explicitly start:

Method 1: Start directly

Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

Method 2: setComponent to start a new component

Intent intent = new Intent();
intent.setComponent(new ComponentName(this, MainActivity.class);)
startActivity(intent);

Method 3: setClassName sets the full path of the full Activity

Intent intent = new Intent();
intent.setClassName(this,"com.dinghe.schemetestmain.MainActivity");
startActivity(intent);        

6.5 Implicit start setting Action:

Method 1: Set Action

Such as calling a system program, system Action

Intent intent = new Intent();
拨打电话
intent.setAction(Intent.ACTION_CALL);
发送短信
intent.setAction(Intent.ACTION_SENDTO);
打开相机
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
//启动
startActivity(intent);

Method 2: If you customize Action, set the action of intent-filter in AndroidManifest.xml

<activity
	android:name=".ActionActivity"
	android:exported="true">
	<intent-filter>
		<action android:name="com.dinghe.schemetest.customerAction"/>
		<category android:name="android.intent.category.DEFAULT" />
   </intent-filter>
</activity>
Intent intent = new Intent();
intent.setAction(getPackageName()+".customerAction");
startActivity(intent);

Method 3: Set action+data and open the website:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));                
startActivity(intent);

Method 4: Set action+data+type to open the specified type of file

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri data = Uri.parse("file:///storage/sdcard0/test.mp3");
//设置data+type属性
intent.setDataAndType(data, "audio/mp3"); //方法:Intent android.content.Intent.setDataAndType(Uri data, String type)
startActivity(intent);  

Method 5: Set action+category+data+extra+flags

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("smsto:"+"10086"));
intent.putExtra("keyName","keyValue");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Note:  If you define an Action to be started implicitly, you must add android.intent.category.DEFAULT to AndroidManifast.xml, otherwise it will not work

Communication between seven activities

7.1 The Intent.putExtra() method is used to transfer data in the Activity, in which any type of data can be transferred, as shown in the figure below to transfer basic types, array types, byte class types

Collection type, and Bundle type 

 

 7.2 Intent transfer data

Intent intent = new Intent(this,MainActivity.class);
intent.putExtra("intKey",1);
intent.putExtra("StringKey","111");
startActivity(intent);

7.3 Bundle transfer data

Intent intent = new Intent(this,MainActivity.class);
Bundle bundle=new Bundle();
bundle.putInt("intKey",1);
bundle.putString("StringKey","111");
intent.putExtras(bundle);
startActivity(intent);

Eight Activity startup process

1. The Launcher process requests AMS

2. AMS sends a request to create an application process

3. The Zygote process accepts the request and incubates the application process

4. The application process starts the ActivityThread

5. The application process is bound to AMS

6. AMS sends a request to start the Activity

7. The Handler of ActivityThread handles the request to start the Activity

Nine Activity Management and Rollback

9.1 Monitor the background and foreground switching of the program, such as returning to the desktop and opening from the desktop.

Use the method of Application.ActivityLifecycleCallbacks to monitor the number of opened activities globally. The number of 0 means that it is in the background, and the number of 1 means that it is in the foreground.

The specific implementation of front and back monitoring is as follows:

private Application.ActivityLifecycleCallbacks activityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
	//打开的Activity数量统计
	private int activityStartCount = 0;

	@Override
	public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

	}

	@Override
	public void onActivityStarted(Activity activity) {
		activityStartCount++;
		//数值从0变到1说明是从后台切到前台
		if (activityStartCount == 1) {
			//从后台切到前台
			
		}
	}

	@Override
	public void onActivityResumed(Activity activity) {

	}

	@Override
	public void onActivityPaused(Activity activity) {

	}

	@Override
	public void onActivityStopped(Activity activity) {
		activityStartCount--;
		//数值从1到0说明是从前台切到后台
		if (activityStartCount == 0) {
			//从前台切到后台
			
		}
	}

	@Override
	public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

	}

	@Override
	public void onActivityDestroyed(Activity activity) {

	}
};

9.2 Define the Activity rollback stack, add the stack in the onCreate of the Activity, and end the specified page or all pages on any page

Create a management tool class for the Activity stack as follows:

public class ActivityUtil {
    public static Stack<Activity> activityStack = new Stack<Activity>();

    /**
     * 添加Activity到堆栈
     */
    public static void addActivity(Activity activity) {
        activityStack.push(activity);
    }

    public static void removeActivity(Activity activity) {
        activityStack.remove(activity);
    }

    /**
     * 获取当前Activity(堆栈中最后一个压入的)
     */
    public static Activity currentActivity() {
        return activityStack.lastElement();
    }

    /**
     * 结束当前Activity(堆栈中最后一个压入的)
     */
    public static void finishCurrentActivity() {
        Activity activity = activityStack.pop();
        activity.finish();
    }

    /**
     * 结束指定的Activity
     */
    public static void finishActivity(Activity activity) {
        if (activity != null) {
//            activityStack.remove(activity);
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }


    /**
     * 结束指定的Activity
     */
    public static void finishActivity(Activity activity,boolean isRemoveStack) {
        if (activity != null) {
            if (!activity.isFinishing()) {
                activity.finish();
                if(isRemoveStack){
                    activityStack.remove(activity);
                }
            }
        }
    }

    public static void finishExcept(Class<?> cls) {
        for (Activity activity : activityStack) {
            if (!activity.getClass().equals(cls)) {
                finishActivity(activity);
            }
        }
    }

    /**
     * 结束指定类名的Activity
     */
    public static void finishActivity(Class<?> cls) {
        for (Activity activity : activityStack) {
            if (activity.getClass().equals(cls)) {
                finishActivity(activity);
            }
        }
    }

    /**
     * 结束所有Activity
     */
    public static void finishAllActivity() {
        for (Activity activity : activityStack) {
            if (activity != null) {
                activity.finish();
            }
        }
        activityStack.clear();
    }

    /**
     * 退出应用程序
     */
    @SuppressLint("MissingPermission")
    public static void AppExit(Context context) {
        try {
            finishAllActivity();
            ActivityManager manager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            manager.killBackgroundProcesses(context.getPackageName());
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Add Activity to stack 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //添加Activity到栈
        ActivityUtil.addActivity(this);
    }
}

End the specified Activity

ActivityUtil.finishActivity(MainActivity.class);

Communication and jumping of twelve apps

10.1 When we usually open JD.com or other apps, we can open another app from within the app, or wechat sharing can directly open the program of wechat, and the webpage H5 can jump to specify other app pages, so how is this realized? This uses cross-process jumps between applications.

10.2 Two apps, one app is used to open another app. To open another app, you must first know the app's package name, and then open the specified activity explicitly or implicitly according to the package name.

10.3 Jump in explicit mode, just like the normal Intent explicit start, you can open it by specifying the package name and type

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName componentName = new ComponentName("com.dinghe.schemetest", "com.dinghe.schemetest.MainActivity");
intent.setComponent(componentName);
startActivity(intent);

10.4 Web page H5 jumps to another app, which is realized through the scheme in the data of the intent-filter.

Scheme is an in-page jump protocol. By defining your own scheme protocol, you can easily jump to various pages in the app; through the scheme protocol, the server can customize and tell the app to jump to the internal page of the app

Implementation steps:

Step 1: create a new html page test.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <!-- <a href="[scheme]://[host]/[path]?[query]">启动应用程序</a> -->
        <!--  scheme:判别启动的App -->
        <!--  host:主机                没有也可以 -->
        <!--  path:传值时必须的key      没有也可以 -->
        <!--  query:获取值的Key和Value  没有也可以 -->
        <a href="goods://test:8080/details?id=222">启动应用</a>
        <br/>
    </body>
</html>

Step 2: Create a new target protocol page SchemeActivity.java

public class SchemeActivity extends AppCompatActivity {
    private TextView tvContent;

    String id;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scheme);

        id=getIntent().getStringExtra("id");



        tvContent = (TextView) findViewById(R.id.tv_content);

        Intent intent = getIntent();
        Uri data = intent.getData();  //
        String action = intent.getAction();
        String scheme = intent.getScheme();
        Set<String> categories = intent.getCategories();
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("data:").append(data).append("\n\n")
                .append("action:").append(action).append("\n\n")
                .append("categories:").append(categories).append("\n\n")
                .append("scheme:").append(scheme).append("\n\n")
                .append("id:").append(data.getQueryParameterNames()).append("\n\n")
                .append("host:").append(data.getHost()).append("\n\n")
                .append("path:").append(data.getPath()).append("\n\n")
                .append("port:").append(data.getPort()).append("\n\n")
                ;


        tvContent.setText(stringBuilder);
    }
}

Step 3: Register SchemeActivity protocol in AndroidManifest.xml

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">
	
	<activity
		android:name=".SchemeActivity"
		android:exported="true"
		android:launchMode="singleTask">
		<intent-filter>
			<action android:name="android.intent.action.VIEW"/>
			<category android:name="android.intent.category.DEFAULT"/>
			<category android:name="android.intent.category.BROWSABLE"/>

			<data android:scheme="goods"
				android:host="test"
				android:port="8080"
				android:path="/details"
				/>

		</intent-filter>
	</activity>

</application>

Step 4: Jump to the agreement, click the start application button in the h5 webpage, and you can jump to another app

 10.6 Use the three-party SDK to realize the scheme of web page jumping to other apps. For example, the Aurora Magic Chain platform can realize this scheme by using this short chain

The following process

 create short chain

Guess you like

Origin blog.csdn.net/qq_29848853/article/details/130645163
Recommended