Подтвердить что ты не робот

Программно возобновить/воссоздать деятельность?

После некоторых изменений в моей базе данных, которые связаны с существенным изменением в моих представлениях, я хотел бы перерисовать, повторно выполнить onCreate.

Как это возможно?

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: Android SDK 11 добавил метод recreate() к действиям.


Я сделал это, просто повторно использовав намерение, положившее начало деятельности. Определите намерение starterIntent в вашем классе и назначьте его в onCreate(), используя starterIntent = getIntent();. Затем, когда вы хотите возобновить действие, позвоните finish(); startActivity(starterIntent);

Это не очень элегантное решение, но это простой способ перезапустить свою деятельность и заставить ее перезагрузить все.

Ответ 2

Вызвать recreate метод активности.

Ответ 3

Объединяя некоторые ответы здесь, вы можете использовать что-то вроде следующего.

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() фактически не действует так же, как полностью воссоздает активность. Это эквивалентно вращению устройства, поэтому, если у вас есть Fragment с setRetainInstance(true), они не будут воссозданы; просто приостановился и возобновился.

Поэтому в настоящее время я не считаю, что есть приемлемое решение.

Ответ 4

Когда мне нужно перезапустить действие, я использую следующий код. Хотя это не рекомендуется.

Intent intent = getIntent();
finish();
startActivity(intent);

Ответ 5

Опция 1

Вызовите recreate() для вашей Activity. Однако этот метод приводит к появлению мигающего черного экрана во время повторного создания действия.

Вариант 2

finish();
startActivity(getIntent());

Здесь нет "мигающего" черного экрана, но вы увидите переход между старым и новым экземплярами с не очень приятным черным фоном. Мы можем сделать лучше.

Вариант 3

Чтобы это исправить, мы можем добавить вызов overridePendingTransition():

finish();
startActivity(getIntent());
overridePendingTransition(0, 0);

До свидания черный экран, но в моем случае я все еще вижу какой-то переход (анимация исчезновения), на этот раз на цветном фоне. Это потому, что вы заканчиваете текущий экземпляр своей деятельности до того, как новый будет создан и станет полностью видимым, а промежуточный цвет является значением windowBackground темы windowBackground.

Вариант 4

startActivity(getIntent());
finish();

Вызов startActivity() finish() после startActivity() будет использовать переход по умолчанию между действиями, часто с небольшой вставкой анимации. Но переход все еще виден.

Вариант 5

startActivity(getIntent());
finish();
overridePendingTransition(0, 0);

Для меня это лучшее решение, потому что оно перезапускает активность без видимого перехода, как будто ничего не произошло.

Это может быть полезно, если, например, в вашем приложении вы предлагаете способ изменить язык отображения независимо от языка системы. В этом случае всякий раз, когда пользователь меняет язык вашего приложения, вы, вероятно, захотите перезапустить свою деятельность без перехода, чтобы переключение языка выглядело мгновенно.

Ответ 6

для API до 11 вы не можете использовать 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

}

Ответ 7

После поиска инструмента для пряников для 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 не имеет запросаRelaunchActivity, однако, из diff, я нашел это:

             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);
             }

Поэтому я думаю, что вместо requestRelaunchActivity можно использовать scheduleRelaunchActivity.

И я написал их с помощью размышлений:

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.

Ответ 8

Если это ваша проблема, вы должны, вероятно, реализовать другой способ сделать вид, заполняющий вашу активность. Вместо повторного запуска onCreate() вы должны сделать так, чтобы onCreate() вызывал ваш метод заполнения некоторым аргументом. Когда данные изменяются, метод заполнения должен вызываться с другим аргументом.

Ответ 9

Как я решил, используя Fragments. Они обратно совместимы до 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();
    }
}

Ответ 10

Вызовите метод recreate() откуда вы хотите воссоздать свою деятельность. Этот метод уничтожит текущий экземпляр Activity с помощью onDestroy() а затем заново onCreate() действие с помощью onCreate().

Ответ 11

Возможно, это перебор, но: fooobar.com/questions/21649/... (перезапускает приложение, обеспечивая обходной путь для проблемы утечки ресурсов собственной библиотеки.)

Ответ 12

Однажды я сделал тестовое приложение, которое загружает, удаляет, а затем перезагружает файл базы данных, используя облачное хранилище Firebase. Для отображения данных в базе данных единственным решением, которое я нашел, был следующий код. Ни recreate(), ни finish() в этом случае не работали.

Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);

Ответ 13

Если вы хотите передать параметр 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);
              }

Ответ 14

Если вы просто хотите повторить свое мнение, у меня была такая же проблема. В функции onResume попробуйте поместить это:

mView = new AndroidPinballView(getApplication());

Это также было в моем onCreate(), поэтому для меня это работало в onResume:)