回答:
更新:Android SDK 11は、recreate()アクティビティにメソッドを追加しました。
アクティビティを開始したインテントを単に再利用することでそれを実現しました。目的を定義しstarterIntent、あなたのクラスで、それが中に割り当てるonCreate()使用starterIntent = getIntent();。その後、アクティビティを再開する場合は、finish(); startActivity(starterIntent);
これは非常に洗練されたソリューションではありませんが、アクティビティを再開して強制的にすべてをリロードさせる簡単な方法です。
finish()直後に電話することを提案しましたstartActivity()...
finish();、その後startActivity(starterIntent);
アクティビティのrecreateメソッドを呼び出します。
recreate()が、再作成時にラジオボタンがリセットされないという奇妙な問題が発生しましたが、今のところfinish(); startActivity(getIntent());これを使用していて、数日または数週間でどのように機能するかを確認しています。
ここでいくつかの答えを組み合わせると、次のようなものを使用できます。
class BaseActivity extends SherlockFragmentActivity
{
// Backwards compatible recreate().
@Override
public void recreate()
{
if (android.os.Build.VERSION.SDK_INT >= 11)
{
super.recreate();
}
else
{
startActivity(getIntent());
finish();
}
}
}
私はそれを少しテストしました、そしていくつかの問題があります:
startActivity(...); finish();はアプリを存在させるだけで、アクティビティを再開しません。super.recreate()実際には、アクティビティを完全に再現するのと同じようには動作しません。これは、デバイスを回転させることと同じです。そのため、Fragments がある場合、setRetainInstance(true)それらは再作成されません。単に一時停止して再開しただけです。だから現在私は許容できる解決策があるとは思いません。
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB代わりに11
startActivity(getIntent());finish();にfinish();startActivity(getIntent());
に電話recreate()してくださいActivity。ただし、この方法では、アクティビティの再作成中に点滅する黒い画面が表示されます。
finish();
startActivity(getIntent());
ここには「点滅する」黒い画面はありませんが、古いインスタンスと新しいインスタンスの間で、あまり快適ではない黒い背景の遷移が表示されます。私たちはもっとうまくやることができます。
これを修正するには、次の呼び出しを追加しますoverridePendingTransition()。
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);
さようなら、黒い画面ですが、今回は、色付きの背景に、何らかの遷移(フェードアニメーション)がまだ表示されています。これは、新しいインスタンスが作成されて完全に表示される前に、アクティビティの現在のインスタンスを終了しているためです。中間の色は、windowBackgroundテーマ属性の値です。
startActivity(getIntent());
finish();
finish() after startActivity()を呼び出すと、アクティビティ間のデフォルトの遷移が使用されます。多くの場合、小さなスライドインアニメーションが使用されます。しかし、移行はまだ見えています。
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
私には、何も起こらなかったかのように、目に見える遷移なしでアクティビティを再開するので、これは最良のソリューションです。
たとえば、アプリでシステムの言語とは無関係に表示言語を変更する方法を公開する場合に役立ちます。この場合、ユーザーがアプリの言語を変更するたびに、移行せずにアクティビティを再開して、言語の切り替えが瞬時に見えるようにする必要があります。
アクティビティを再開する必要がある場合は、次のコードを使用します。それはお勧めできませんが。
Intent intent = getIntent();
finish();
startActivity(intent);
11より前のAPIでは、recreate()を使用できません。私はこのように解決しました:
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
そしてonCreate ..
@Override
public void onCreate(Bundle savedInstanceState) {
if (getIntent().hasExtra("bundle") && savedInstanceState==null){
savedInstanceState = getIntent().getExtras().getBundle("bundle");
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//code
}
のgingerbread実装を探した後recreate、次のコード(gingerbread用)を使用したいと思います。
activity.mMainThread.mAppThread.scheduleRelaunchActivity(activity.mToken, null, null, 0, false, null);
これらのコードの場合、それはより高いAPIの実装からのものです。
public void recreate() {
if (mParent != null) {
throw new IllegalStateException("Can only be called on top-level activity");
}
if (Looper.myLooper() != mMainThread.getLooper()) {
throw new IllegalStateException("Must be called from main thread");
}
mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, false);
}
Api-10にはrequestRelaunchActivityがありませんが、差分から、これを見つけました:
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config) {
- ActivityClientRecord r = new ActivityClientRecord();
-
- r.token = token;
- r.pendingResults = pendingResults;
- r.pendingIntents = pendingNewIntents;
- r.startsNotResumed = notResumed;
- r.createdConfig = config;
-
- synchronized (mPackages) {
- mRelaunchingActivities.add(r);
- }
-
- queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
+ requestRelaunchActivity(token, pendingResults, pendingNewIntents,
+ configChanges, notResumed, config, true);
}
ので、scheduleRelaunchActivity代わりに使用できると思いますrequestRelaunchActivity。
そして、私は反射を使用してそれらを書きました:
package me.piebridge.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Build;
import android.os.IBinder;
public class GingerBreadUtil {
private static Field scanField(Class<?> clazz, String... names) {
for (String name : names) {
Field field;
try {
field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
}
try {
field = clazz.getField(name);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
}
}
return null;
}
public static void recreate(Activity activity) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
recreateHC(activity);
} else {
try {
recreateGB(activity);
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static void recreateHC(Activity activity) {
((Activity) activity).recreate();
}
private static void recreateGB(Activity activity) throws IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Field Activity$mToken = scanField(Activity.class, "mToken");
IBinder mToken = (IBinder) Activity$mToken.get(activity);
Field Activity$mMainThread = scanField(Activity.class, "mMainThread");
Object mMainThread = Activity$mMainThread.get(activity);
Field ActivityThread$mAppThread = scanField(mMainThread.getClass(), "mAppThread");
Object mAppThread = ActivityThread$mAppThread.get(mMainThread);
Method method = mAppThread.getClass().getMethod("scheduleRelaunchActivity",
IBinder.class, List.class, List.class, int.class, boolean.class, Configuration.class);
method.invoke(mAppThread, mToken, null, null, 0, false, null);
}
}
Xposedフレームワークのバックポーティングにこれらのコードを使用しています。
Build.VERSION_CODES.ECLAIR_MR1(v7)と下位互換性があります。古いバージョンでも動作する可能性があります。
これが問題である場合は、アクティビティを埋めるビューを実行する別の方法を実装する必要があります。再実行onCreate()する代わりにonCreate()、いくつかの引数を指定してfillメソッドを呼び出すようにする必要があります。データが変更されると、fillingメソッドは別の引数で呼び出されます。
私がそれを解決した方法は、フラグメントを使用することです。これらは、サポートライブラリを使用してAPI 4まで下位互換性があります。
FrameLayoutを含む「ラッパー」レイアウトを作成します。
例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
次に、いつでも好きなときにFrameLayoutを置き換えることができるFragmentActivityを作成します。
例:
public class SampleFragmentActivity extends FragmentActivity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.wrapper);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null)
{
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null)
{
return;
}
updateLayout();
}
}
private void updateLayout()
{
Fragment fragment = new SampleFragment();
fragment.setArguments(getIntent().getExtras());
// replace original fragment by new fragment
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
}
通常、アクティビティのonCreateを使用するのと同じように、フラグメント内で、onStartおよびonCreateViewを使用してインフレート/置換できます。
例:
public class SampleFragment extends Fragment
{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.yourActualLayout, container, false);
}
@Override
public void onStart()
{
// do something with the components, or not!
TextView text = (TextView) getActivity().findViewById(R.id.text1);
super.onStart();
}
}
かつて、firebaseクラウドストレージを使用してデータベースファイルをアップロード、削除、再ダウンロードするテストアプリを作成しました。データベース内のデータを表示するには、次のコードが私が見つけた唯一のソリューションでした。この場合もどちらrecreate()もfinish()機能しませんでした。
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);
データが変更されたときにフラグメントを更新する最良の方法を見つけました
「検索」ボタンがある場合は、ボタン内のARRAYリストを初期化する必要があります
mSearchBtn.setOnClickListener(new View.OnClickListener(){
@Override public void onClick(View v){
mList = new ArrayList<Node>();
firebaseSearchQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Node p = dataSnapshot1.getValue(Node .class);
mList.add(p);
}
YourAdapter = new NodeAdapter(getActivity(), mList);
mRecyclerView.setAdapter(YourAdapter );
}
onCreate()にパラメーターを渡したい場合は、追加で新しいインテントを作成し、それを使用してStartActivityを呼び出す必要があります。これは私がこの方法を使って行った簡単な例です。
String eczSabit = sa.getItem(position).getValue();
if(!Util.IsNullOrEmpty(eczSabit)){
sabit = Long.parseLong(eczSabit);
Intent intent = new Intent(eczaneSegmentasyon.this,eczaneSegmentasyon.class);
intent.putExtra("sabit", sabit);
startActivity(intent);
}