@VidarWahlbergあなたの答えは良いFragmentActivity
ですが、タスクを実行する場所があり、FragmentActivity
非同期が終了する前、またはアプリがバックグラウンドで実行される前に開く新しいものを開くとしましょう(例:ホームをクリックしました)。BaseActivity
拡張する場所を作成しFragmentActivity
、すべての活動がそれを拡張することをお勧めします。
何が重要ですか?
@VidarWahlbergが彼の回答で述べたように、BaseActivity
が必要でありstatic FragmentManager fm;
、それを子アクティビティで使用してDialogFragment
.
違いはなんですか?
fm = getSupportFragmentManager();
メソッドで初期化する代わりに、でonStart()
行う必要がありますonResume()
。スレッド実行アクティビティを開始すると、その新しいインスタンスが作成され、次のアクティビティを開始すると、初期化されるBaseActivity
場所の新しいインスタンスが作成FragmenManager
され、スレッド開始アクティビティfm
オブジェクトに戻ると、2 番目のアクティビティ(一時停止されている) インスタンス。すでに一時停止しているアクティビティのビューでダイアログを表示しようとすると、アプリケーションがクラッシュします。onResume()
一時停止したアクティビティのビューを変更することはできないため、呼び出されるたびに初期化する必要があります。onResume()
アクティビティの開始時にも呼び出されるため、安全に初期化できますFragmentManager
。
他に何を心配する必要がありますか?
すべてがうまくいっていると思うかもしれませんが、そうではありません。最初は気付かないかもしれませんが、アプリがフォアグラウンドではなく (バックグラウンド) である場合、すべてのアクティビティは一時停止されますが、スレッドは既に開始され、実行されています。これは、スレッドが継続して表示しようとするDialogFragmernt
(または、フォーカスされていないアクティビティのビューを変更するとしましょう) ため、問題です。したがって、解決策は、アプリがフォアグラウンドにあるかどうかを追跡することです。これは実行できますがPackageManager
、マニフェスト ファイルで新しいアクセス許可が必要になります (ユーザーはこれを好まず、アプリをインストールしたくない場合があります)。解決策は、withおよびwithstatic boolean isOnBackground = false;
のすべてのアクティビティで変更するフィールドを用意することです。これは大きな変化ではないので、onResume()
isOnBackground = false;
onPause()
isOnBackground = true;
BaseActivity
それができるところです。BaseActivity
新しいアクティビティが開始されるたびにクラスの新しいインスタンスが作成されるため、これは安全ですが、フィールドはstatic
一度だけ作成され、すべてのインスタンスで同じであるためです。isOnBackground
スレッド ポスト メソッドの本体コードを開始する前に、状態を確認する必要があります。
onPause()
との間の遅延が原因で問題が発生する可能性があると言うかもしれませんが、onResume()
アクティビティをすばやく開始し、UI スレッドで長時間かかる作業を行わないようにアプリを設計する必要があります (バックグラウンド スレッドで行う必要があります)。したがって、アプリが適切に設計されている場合、問題は発生しません:)
アプリがフォアグラウンドにないときはいつでも、スレッド実行メソッドの再帰呼び出しを使用できます。アプリの状態がリセットされた場合 (メモリが必要な場合)、またはアプリがユーザーによって停止された場合、または Android 自体がループを停止した場合、すべてのアプリのインスタンスがメモリから解放されるため、これは安全でループを引き起こしません。
注: Android サポート ライブラリを使用してください。
コードは次のとおりです。
BaseActivity.java
.......................
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
.......................
public class BaseActivity extends FragmentActivity {
public static FragmentManager fm;
public static boolean isOnBackground;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
BaseActivity.isOnBackground = false;
BaseActivity.fm = getSupportFragmentManager();
}
@Override
protected void onPause() {
super.onPause();
BaseActivity.isOnBackground = true;
}
}
MainActivity.java
.....................
import android.support.v4.app.DialogFragment;
.....................
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//This is just to call some second activity
Button startNewActivity = (Button) findViewById(R.id.helloWorld);
startNewActivity.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
SecondActivity.class);
startActivity(intent);
}
});
showEditDialog();
}
private void showEditDialog() {
(new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
if(!BaseActivity.isOnBackground) {
DialogFragment myFragmentDialog = new DialogFragment();
myFragmentDialog.show(BaseActivity.fm,
"fragment_my_dialog");
} else {
//this is optional
showEditDialog();
}
}
}, 15000);
}
}