初めて学び始めたときは、意図はとてもシンプルだと感じていたのを覚えていますが、今ではいつも意図に悩まされ、素朴すぎます。わかりやすくするために、まとめてみましょう。
1つ、onNewIntent
古いルール、最初に公式を見てください:
おそらく、アクティビティがsingleTop
モードで開始するように設定されているとき、そしてこのアクティビティのアクティベーション要求に再度応答する必要があるとき、スタックの一番上にある既存のアクティビティを再利用することを意味しますonNewIntentメソッドを呼び出します。また、新しく送信されたインテント(onNewIntentメソッド)を受け入れる前に、onPauseメソッドを最初に実行する必要があります。
2つ目は、onNewIntentとスタートアップモードです。
前提条件:ActivityAが開始されており、現在のアプリケーションのアクティビティタスクスタックにあります。
ActivityAのLaunchModeが標準の場合:
ActivityAの各開始は新しいインスタンスを開始することであるため、元の開始とは関係がなく、元のActivityAのonNewIntentメソッドは呼び出されません。
ActivityAのLaunchModeがSingleTopの場合:
ActivityAがスタックの最上位にあり、ActivityAを今すぐ開始する場合、この時点でonNewIntent()メソッドが呼び出され、ライフサイクルシーケンスは次のようになります。
onCreate—> onStart—> onResume— onPause
—> onNewIntent
—>onResume
LaunchMode ActivityAがSingleInstance
、の場合SingleTask
:
ActivityAがすでにタスクスタックにある場合は、ActivityAを再度開始すると、この時点でonNewIntent()メソッドが呼び出され、ライフサイクルの呼び出しシーケンスは次のようになります。
onPause—>他のページにジャンプ—> onCreate—> onStart—> onResume—onPause—>ジャンプA—> onNewIntent
—> onRestart
—> onStart
—>onResume
一般に、SingleTop
(およびスタックの最上位にある)、SingleTask
およびSingleInstance
(およびタスクスタックにすでにインスタンスが存在する)場合にのみ、それらは再起動時に呼び出されます。つまり、startActivityに対してのみ有効であり、フォアグラウンドへのバックグラウンド再度開始されない場合、onNewIntentはトリガーされません。
3.例:
Androidでは、別のアクティビティから新しいアクティビティを開始し、それにデータを渡すことは簡単で基本的なことです。ただし、すでに実行中のアクティビティをフォアグラウンドに表示してデータを渡す場合は、少し注意が必要です。
まず、デフォルトでは、インテントを使用してアクティビティを呼び出すと、別のインスタンスがすでに実行されている場合でも、アクティビティの新しいインスタンスが作成されて表示されます。この状況を回避するには、アクティビティを複数回インスタンス化しないようにマークする必要があります。これを実現するために、AndroidManifest.xmlでアクティビティのlaunchModeをsingleTopに設定します
<activity android:name=".SecondActivity"
android:launchMode="singleTop"
></activity>
<activity
android:name=".FirstActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
このように、インテントを使用してこのアクティビティを呼び出すと、既存のインスタンスが存在する場合、システムはリクエストをそのインスタンスにリダイレクトします。今回は通常のonCreateメソッドは実行されません。
その名前が示すように、アクティビティが作成されたときに実行され、今回はすでに存在しているため、onNewIntent()メソッドが呼び出されます。
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);//must store the new intent unless getIntent() will return the old one
processExtraData();
}
onCreateでは通常の方法でデータを受信できることを忘れないでください。アクティビティが初めて作成されるとき、システムはリターンラウンドでアクティビティを簡単に終了できるため、これが発生した場合は、代わりにonCreateメソッドが呼び出されます。 onNewIntentの。
したがって、洗練されたソリューションでは、同じ関数を呼び出して、onCreateとonNewIntentからのジャンプを処理できます。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
processExtraData();
}
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);//must store the new intent unless getIntent() will return the old one
processExtraData()
}
private void processExtraData(){
Intent intent = getIntent();
//use the data received here
}
完全なコードは次のとおりです。
FirstActivity.java
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
displayIntentData();
findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("key",((EditText)findViewById(R.id.dataToSend)).getText().toString());
startActivity(intent);
//注意我们在这里没有调用finish()方法
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.e("onNewIntent","First Activity OnNewIntent is called");
setIntent(intent);//must store the new intent unless getIntent() will return the old one
displayIntentData();
}
private void displayIntentData(){
Intent intent = getIntent();
TextView tv = (TextView)findViewById(R.id.intentData);
Bundle extras=intent.getExtras();
if(extras!=null){
tv.setText("Data received: "+extras.getString("key"));
}else{
tv.setText("No extradata received");
}
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
displayIntentData();
findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
intent.putExtra("key",((EditText)findViewById(R.id.dataToSend)).getText().toString());
startActivity(intent);
//注意我们在这里没有调用finish()方法
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
displayIntentData();
}
private void displayIntentData(){
Intent intent = getIntent();
TextView tv = (TextView)findViewById(R.id.intentData);
Bundle extras=intent.getExtras();
if(extras!=null){
tv.setText("Data received: "+extras.getString("key"));
}else{
tv.setText("No extradata received");
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myonnewintenttest">
<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=".SecondActivity"
android:launchMode="singleTop"
></activity>
<activity
android:name=".FirstActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstActivity">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/intentData"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<EditText
android:layout_height="wrap_content"
android:id="@+id/dataToSend"
android:layout_width="fill_parent"
android:hint="Data to send"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/intentData"
/>
<Button
android:text="Send"
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/dataToSend"
/>
</androidx.constraintlayout.widget.ConstraintLayout>