Ответы:
ОБНОВЛЕНИЕ : в Android SDK 11 добавлен recreate()метод действий.
Я сделал это, просто повторно используя намерение, с которого началось действие. Определите намерение starterIntentв своем классе и назначьте его onCreate()использованию starterIntent = getIntent();. Затем, когда вы захотите перезапустить действие, позвонитеfinish(); startActivity(starterIntent);
Это не очень элегантное решение, но это простой способ перезапустить вашу деятельность и заставить ее перезагрузить все.
finish()сразу после этого startActivity()именно по этой причине ...
finish();Тогда я добился этого, позвонив первымstartActivity(starterIntent);
Вызовите метод воссоздания действия.
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() после startActivity() будет использоваться переход между действиями по умолчанию, часто с небольшой скользящей анимацией. Но переход все же виден.
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
Для меня это лучшее решение, потому что оно перезапускает активность без видимого перехода, как будто ничего не произошло.
Это может быть полезно, если, например, в вашем приложении вы предоставляете способ изменить язык отображения независимо от языка системы. В этом случае всякий раз, когда пользователь меняет язык вашего приложения, вы, вероятно, захотите перезапустить свою деятельность без перехода, чтобы переключение языка выглядело мгновенно.
Когда мне нужно перезапустить действие, я использую следующий код. Хотя это не рекомендуется.
Intent intent = getIntent();
finish();
startActivity(intent);
для API до 11 вы не можете использовать воссоздать (). Я решил так:
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
}
После поиска имбирного пряника recreateя хотел бы использовать следующие коды (для имбирного пряника):
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 framework.
Build.VERSION_CODES.ECLAIR_MR1(v7). Это может работать и на более старых версиях.
Если это ваша проблема, вам, вероятно, следует реализовать другой способ заполнения представления в Activity. Вместо повторного запуска onCreate()вы должны сделать так, чтобы onCreate()ваш метод заполнения вызывал некоторый аргумент. При изменении данных метод заполнения должен вызываться с другим аргументом.
Я решил это с помощью фрагментов . Они обратно совместимы до 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>
Затем вы создаете FragmentActivity, в котором вы можете заменить FrameLayout в любое время.
Пример:
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();
}
Во фрагменте, который вы надуваете / заменяете, вы можете использовать onStart и onCreateView, как если бы вы обычно использовали onCreate действия.
Пример:
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 (новый 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);
}
Если вы просто хотите переделать свой взгляд, у меня была точно такая же проблема. В onResumeфункции попробуйте поместить это:
mView = new AndroidPinballView(getApplication());
Это тоже было у меня onCreate(), так что положив это на работу onResumeдля меня :)