The more you explore, the deeper you go - Uncover the advanced play of activity


In the previous article, we have explored the basic knowledge of Activity, including its essential composition, lifecycle management, startup mode and other core contents. But the real power of Activity is far more than that. It also has many advanced features, enabling us to create a more flexible and powerful Android application experience. Today, let me take you to dig deeply into those unique skills behind Activity!


1、 Recovery and reconstruction: the elixir of data state

When an activity is rebuilt, such as configuration changes caused by device rotation, the temporary data held previously will be lost. In order to solve this problem, Android system provides two main state saving schemes.


Scheme 1: Temporary storage of key data with Bundle

The onSaveInstanceState callback in Activity is generated for this purpose. When the system is ready to destroy an Activity instance, it will first call this method and pass in a Bundle for us to temporarily store data:

 public class MyActivity extends AppCompatActivity { private static final String KEY_DATA = "key_data"; private String data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState !=  null) { data = savedInstanceState.getString(KEY_DATA); } } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putString(KEY_DATA, data); } }

When the activity is rebuilt, the system will automatically send the previous Bundle data back to the onCreate method, so we can recover the original state information from it. In this way, temporary data can be retained across the reconstructed gap.


Solution 2: ViewModel solves the ultimate data hosting

Although the Bundle method is direct and effective, sometimes the code is too long. A better choice is to use the built-in ViewModel component in the AndroidX library to completely entrust the state data management to this special manager:

 public class MyViewModel extends ViewModel { private Data currentData; public Data getCurrentData() { return currentData; } public void setData(Data data) { currentData = data; } }
 public class MyActivity extends AppCompatActivity { private MyViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewModel = new ViewModelProvider(this).get(MyViewModel.class); if (viewModel.getCurrentData() !=  null) { renderData(viewModel.getCurrentData()); } } private void renderData(Data data) { viewModel.setData(data); //TODO: update UI } }

The lifecycle of the ViewModel is bound to the ownership relationship of the current activity, and does not depend on the specific instance of the activity. This means that ViewModel can maintain data continuity and consistency no matter how many times an activity is rebuilt.

In addition to solving the problem of data loss, ViewModel also has many other advantages, such as perceiving page navigation status, supporting work process coordination, etc. Therefore, in actual development, ViewModel is undoubtedly the best choice for state recovery practices.


2、 All knowing: Intent's multiple accurate control

When we want to launch a new activity, the indispensable thing is Intent, the "escort" in the Android world. It is not only powerful, but also flexible in use.

1. Explicit Intent

If we clearly know the target activity we want to start, we can directly specify it through explicit Intent:

 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String data = "Hello"; Intent intent = new Intent(this,  TargetActivity.class); intent.putExtra("KEY_DATA", data);  startActivity(intent); } }
 public class TargetActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_target); String data = getIntent().getStringExtra("KEY_DATA"); //TODO: process data } }

2. Implicit Intent

Implicit Intent exposes its service capabilities by declaring Intent Filter in AndroidManifest.xml:

 <!--  AndroidManifest.xml --> <activity android:name=".ShareActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> </activity>
 public class SenderActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sender); Intent intent = new Intent(); intent.setAction(Intent. ACTION_SEND); intent.putExtra(Intent. EXTRA_TEXT,  "Hello"); intent.setType("text/plain"); StartActivity (Intent. createChooser (intent, "shared text")); } }

In this way, all qualified activities can be regarded as the response target of the "Share Text" behavior by the system. You can also freely select from multiple alternatives. In this way, implicit Intent gives the Android ecosystem greater flexibility and scalability.


3、 StartActivityForResult: Start and get the return

In addition to the normal startup mode, Intent also supports the "startup callback" mode.

startActivityForResult Is a method in Android that allows a Activity Start another Activity And wait for the results.

Started Activity You can complete a task (such as filling out a form, selecting a picture, etc.), and then click RESULT_OK or RESULT_CANCELED The result code passes the result back to the original Activity

The following are startActivityForResult For a typical use case of, suppose we want to MainActivity Start one in SecondActivity To obtain the score entered by the user and return the result to:


1. Step 1: In MainActivity Start in SecondActivity And receive the results


 import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView scoreTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); scoreTextView = findViewById(R.id.score_text_view); Button getScoreButton = findViewById(R.id.get_score_button); getScoreButton.setOnClickListener(new View. OnClickListener() { @Override public void onClick(View v) { //Start SecondActivity with startActivityForResult Intent intent = new Intent(MainActivity.this,  SecondActivity.class); startActivityForResult(intent, 1); //  1 is the request code } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //Check whether the request code matches if (requestCode == 1) { //Inspection result code if (resultCode == RESULT_OK) { //Get the returned data int score = data.getIntExtra("score", 0); scoreTextView.setText("Your score is: " + score); } else { //The result code is not RESULT_OK, indicating that the user canceled the operation scoreTextView.setText("No score was entered."); } } super.onActivityResult(requestCode, resultCode, data); } }

Step 2: In the SecondActivity Get user input in and return results

 import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.content.Intent; public class SecondActivity extends AppCompatActivity { private EditText scoreEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); scoreEditText = findViewById(R.id.score_edit_text); Button submitButton = findViewById(R.id.submit_button); submitButton.setOnClickListener(new View. OnClickListener() { @Override public void onClick(View v) { //Get the score entered by the user int score = Integer.parseInt(scoreEditText.getText().toString()); //Create a new Intent to pass the results Intent resultIntent = new Intent(); resultIntent.putExtra("score", score); //End SecondActivity and pass the results setResult(RESULT_OK, resultIntent); finish(); } }); } }

In this example:

  1. MainActivity There is a button. When the user clicks this button, the startActivityForResult start-up SecondActivity one It is the request code defined by us to distinguish onActivityResult Different requests in.
  2. SecondActivity An edit box is provided for users to enter scores, and there is a submit button. When the user clicks the submit button, the entered score will be obtained and put into a Intent Medium, and via setResult Method sends the result back to the Activity , and then end yourself.
  3. When SecondActivity At the end, MainActivity Of onActivityResult The method will be called. By checking the request code( requestCode )And result code( resultCode ), MainActivity You can determine whether the results are valid, and update the UI to display the scores entered by the user.

use startActivityForResult Can be well managed Activity The interaction and result transmission between them make the logic clearer and easier to maintain.


4、 Boundless: URI routing and Scheme protocol access


Intent not only carries the internal component interconnection of Android, but also creates new infinite possibilities with the development of technology. By supporting URI paths, Intent has achieved seamless connection with mobile browsers, opening a new door for our applications.


1. Elaborate: register URI path

First, we need to register a URI path in AndroidManifest.xml for the activity to be exposed:

 <activity android:name=".uri.UriActivity" android:exported="true"> <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:host="www.myapp.com" android:pathPrefix="/uri" android:scheme="https" /> </intent-filter> </activity>

In the above example, we declared a scheme of "https" and a host of“ Www.myapp.com "and the path prefix is"/uri ". This means that as long as the external application emits https://www.myapp.com/uri/ * To open the activity.


2. Pattern recognition: Resolve the incoming URI

Next, the activity needs to provide the ability to parse the URI to obtain the data implied in it:

 public class UriActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_uri); Intent intent = getIntent(); Uri uri = intent.getData(); if (uri !=  null) { String path = uri.getPath(); //  Get Path String param = uri.getQueryParameter("key"); //  Get Parameters //TODO: Process the acquired data } } }

By parsing the obtained Uri object, we can easily obtain the request path, parameters and other key information. This undoubtedly lays the foundation for building a complex routing system.


3. Scheme has no boundary: connected with external channels


In addition to connecting with the browser, our application can also use Scheme to connect with other applications to build a three-dimensional and broad communication network. As long as a unique Scheme protocol within the package name range is agreed and matched with an appropriate Intent Filter, a rich service interface can be provided for external applications:

 <!--  AndroidManifest.xml of other applications --> <activity android:name=". SchemeActivity" android:exported="true"> <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:host="open" android:scheme="myapp" /> </intent-filter> </activity>
 //Request from our app String uri = " myapp://open?data=hello "; Intent intent = new Intent(Intent. ACTION_VIEW, Uri.parse(uri)); startActivity(intent);

The above code will invoke the SchemeActivity of the target application and pass the "data=hello" parameter. In this way, we can connect and share resources with various applications, and create a lively and integrated intelligent experience.


The prologue is not over: more exploration is still going on

This paper discusses some advanced features of Activity as the core of the four components of Android, including saving and restoring state data, fine control of Intent, application of callback mechanism, and future oriented Uri routing and Scheme communication. But the charm of Activity is far more than that. It also contains more profound ideas and opportunities to be explored.


  • twenty-one
    give the thumbs-up
  • step on
  • fourteen
    Collection
    Think it's good? One click collection
  •  Reward
    Reward
  • zero
    comment

Is "relevant recommendation" helpful to you?

  • Very unhelpful
  • No help
  • commonly
  • to be helpful to
  • Very helpful
Submit
comment
Add Red Packet

Please fill in the red envelope greeting or title

individual

The minimum number of red packets is 10

element

The minimum amount of red packet is 5 yuan

Current balance three point four three element Go to recharge>
To be paid: ten element
Achieve 100 million technicians!
After receiving, you will automatically become a fan of the blogger and the red envelope owner rule
hope_wisdom
Red packet sent

Reward the author

W rain or shine w

Your encouragement will be the greatest impetus for my creation

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
Scan code for payment: ¥1
Obtaining
Scan code for payment

Your balance is insufficient, please change the scanning code to pay or Recharge

Reward the author

Paid in element
Payment with balance
Click to retrieve
Scan code for payment
Wallet balance zero

Deduction description:

1. The balance is the virtual currency of wallet recharge, and the payment amount is deducted at a ratio of 1:1.
2. The balance cannot be directly purchased and downloaded, but VIP, paid columns and courses can be purchased.

Balance recharge