Respuestas:
ACTUALIZACIÓN : Android SDK 11 agregó un recreate()método a las actividades.
Lo hice simplemente reutilizando la intención que inició la actividad. Defina una intención starterIntenten su clase y asígnela onCreate()usando starterIntent = getIntent();. Luego, cuando quieras reiniciar la actividad, llamafinish(); startActivity(starterIntent);
No es una solución muy elegante, pero es una forma sencilla de reiniciar tu actividad y obligarla a recargar todo.
finish()inmediatamente después del startActivity()precisamente por esa razón ...
finish();luegostartActivity(starterIntent);
Llame al método recrear de la actividad.
recreate()pero ahora veo un problema extraño en el que los botones de radio no se restablecen cuando se vuelven a crear, pero lo hacen cuando, finish(); startActivity(getIntent());así que lo estoy usando por ahora y veo cómo funciona en los próximos días o semanas.
Combinando algunas respuestas aquí, puede usar algo como lo siguiente.
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();
}
}
}
Lo probé un poco y hay algunos problemas:
startActivity(...); finish();solo existe a la aplicación y no reinicia la actividad.super.recreate()en realidad, no actúa de la misma manera que recrear totalmente la actividad. Es equivalente a rotar el dispositivo, por lo que si tiene mensajes de Fragmentcorreo setRetainInstance(true)electrónico, no se volverán a crear; simplemente hizo una pausa y reanudó.Así que actualmente no creo que haya una solución aceptable.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMBen lugar de usar11
startActivity(getIntent());finish();afinish();startActivity(getIntent());
Llame recreate()a su Activity. Sin embargo, este método hace que aparezca una pantalla negra intermitente durante la recreación de la actividad.
finish();
startActivity(getIntent());
Aquí no hay pantalla negra "parpadeante", pero verá una transición entre las instancias antiguas y nuevas con un fondo negro no tan agradable. Podemos hacerlo mejor.
Para solucionar esto, podemos agregar una llamada a overridePendingTransition():
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);
Adiós pantalla negra, pero en mi caso todavía veo algún tipo de transición (una animación de desvanecimiento), esta vez sobre un fondo de color. Esto se debe a que está terminando la instancia actual de su actividad antes de que se cree la nueva y se vuelva completamente visible, y el color intermedio es el valor del windowBackgroundatributo del tema.
startActivity(getIntent());
finish();
Llamar finish() después startActivity() utilizará la transición predeterminada entre actividades, a menudo con una pequeña animación deslizante. Pero la transición aún es visible.
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
Para mí, esta es la mejor solución porque reinicia la actividad sin ninguna transición visible, como si no pasara nada.
Podría ser útil si, por ejemplo, en su aplicación expone una forma de cambiar el idioma de visualización independientemente del idioma del sistema. En este caso, siempre que el usuario cambie el idioma de su aplicación, probablemente querrá reiniciar su actividad sin transición, haciendo que el cambio de idioma parezca instantáneo.
Cuando necesito reiniciar una actividad, uso el siguiente código. Aunque no se recomienda.
Intent intent = getIntent();
finish();
startActivity(intent);
para API anteriores a 11, no puede usar recreate (). Resolví de esta manera:
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
y en 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
}
Después de buscar el implemento de pan de jengibre recreate, me gustaría usar los siguientes códigos (para pan de jengibre):
activity.mMainThread.mAppThread.scheduleRelaunchActivity(activity.mToken, null, null, 0, false, null);
Para estos códigos, proviene de la implementación en una api superior.
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 no tiene requestRelaunchActivity, sin embargo, desde el diff, encontré esto:
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);
}
Entonces creo que podría usar en scheduleRelaunchActivitylugar de requestRelaunchActivity.
Y los he escrito usando reflect:
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);
}
}
Estoy usando estos códigos para el back-porting de xposed framework.
Build.VERSION_CODES.ECLAIR_MR1(v7). También puede funcionar en versiones anteriores.
Si este es su problema, probablemente debería implementar otra forma de completar la vista en su Actividad. En lugar de volver a ejecutarlo onCreate(), debe hacer que onCreate()llame a su método de llenado con algún argumento. Cuando los datos cambian, el método de relleno debería llamarse con otro argumento.
La forma en que lo resolví es usando Fragmentos . Estos son compatibles con versiones anteriores hasta API 4 mediante el uso de la biblioteca de soporte.
Realiza un diseño "contenedor" con un FrameLayout en él.
Ejemplo:
<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>
Luego, crea una FragmentActivity en la que puede reemplazar el FrameLayout en cualquier momento que desee.
Ejemplo:
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();
}
En el Fragmento que infla / reemplaza, puede usar onStart y onCreateView como normalmente usaría onCreate de una actividad.
Ejemplo:
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();
}
}
Una vez hice una aplicación de prueba que carga, elimina y luego vuelve a descargar el archivo de base de datos usando el almacenamiento en la nube de firebase. Para mostrar los datos en la base de datos, el siguiente código fue la única solución que encontré. Ni recreate()tampoco finish()funcionó en este caso.
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);
Descubrí la mejor manera de actualizar su Fragmento cuando cambian los datos
si tiene un botón "buscar", debe inicializar su lista ARRAY dentro del botón
mSearchBtn.setOnClickListener (nuevo View.OnClickListener () {
@Override public void onClick (Ver 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 );
}
Si desea pasar un parámetro a onCreate (), entonces debe crear una nueva intención agregando extra y llamar a StartActivity con ella. Aquí hay un ejemplo simple que hice de esta manera.
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);
}
Si solo está buscando rehacer su vista, tuve exactamente el mismo problema. En la onResumefunción, intente poner esto:
mView = new AndroidPinballView(getApplication());
Esto también estaba en mi onCreate(), así que poner esto en el onResumetrabajo para mí :)