Yanıtlar:
GÜNCELLEME : Android SDK 11 recreate(), etkinliklere bir yöntem ekledi .
Bunu sadece etkinliği başlatan amacı yeniden kullanarak yaptım. Bir niyet tanımla starterIntentsınıfınızda ve içinde atamak onCreate()kullanarak starterIntent = getIntent();. Ardından etkinliği yeniden başlatmak istediğinizdefinish(); startActivity(starterIntent);
Çok zarif bir çözüm değil, ancak aktivitenizi yeniden başlatmanın ve her şeyi yeniden yüklemeye zorlamanın basit bir yolu.
finish()hemen sonra aramayı önerdim startActivity()...
finish();o zaman çağırarak başardımstartActivity(starterIntent);
Aktivitenin yeniden oluşturma yöntemini çağırın .
recreate()ancak şimdi radyo düğmelerinin yeniden oluştururken sıfırlanmadığı garip bir sorun görüyorum, ancak bu finish(); startActivity(getIntent());yüzden bunu şimdilik kullanıyorum ve önümüzdeki günlerde veya haftalarda nasıl çalıştığını görüyorum.
Burada bazı cevapları birleştirerek aşağıdaki gibi bir şey kullanabilirsiniz.
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();
}
}
}
Biraz test ettim ve bazı sorunlar var:
startActivity(...); finish();sadece app var ve yok aktiviteyi yeniden başlatın.super.recreate()aslında aktiviteyi tamamen yeniden yaratmakla aynı şekilde davranmaz. Cihazı döndürmeye eşdeğerdir, böylece herhangi bir Fragmente- setRetainInstance(true)postanız varsa yeniden oluşturulmazlar; yalnızca duraklatıldı ve yeniden başlatıldı.Bu yüzden şu anda kabul edilebilir bir çözüm olduğuna inanmıyorum.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMBkullanmak yerine11
startActivity(getIntent());finish();görefinish();startActivity(getIntent());
Çağrı recreate()Aşağıdaki yerlerde de Activity. Ancak bu yöntem, etkinliğin yeniden oluşturulması sırasında yanıp sönen siyah bir ekranın görünmesine neden olur.
finish();
startActivity(getIntent());
Burada "yanıp sönen" siyah ekran yok, ancak eski ve yeni örnekler arasında pek hoş olmayan siyah bir arka plana sahip bir geçiş göreceksiniz. Daha iyisini yapabiliriz.
Bunu düzeltmek için şu numaraya bir çağrı ekleyebiliriz overridePendingTransition():
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);
Elveda siyah ekran, ama benim durumumda hala bu sefer renkli bir arka planda bir tür geçiş (solma animasyonu) görüyorum. Bunun nedeni, etkinliğinizin mevcut örneğini yenisi oluşturulmadan ve tam olarak görünür hale gelmeden önce bitirmeniz ve aradaki renk, windowBackgroundtema özelliğinin değeridir .
startActivity(getIntent());
finish();
finish() Sonra arama startActivity(), genellikle küçük bir kayan animasyonla etkinlikler arasındaki varsayılan geçişi kullanacaktır. Ancak geçiş hala görülebilir.
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
Bana göre bu en iyi çözüm çünkü hiçbir şey olmamış gibi aktiviteyi görünür bir geçiş olmadan yeniden başlatıyor.
Örneğin, uygulamanızda görüntüleme dilini sistemin dilinden bağımsız olarak değiştirmenin bir yolunu açıklarsanız yararlı olabilir. Bu durumda, kullanıcı uygulamanızın dilini her değiştirdiğinde, muhtemelen geçiş yapmadan etkinliğinizi yeniden başlatmak isteyeceksiniz, bu da dil geçişinin anında görünmesini sağlayacaktır.
Bir aktiviteyi yeniden başlatmam gerektiğinde aşağıdaki kodu kullanıyorum. Tavsiye edilmese de.
Intent intent = getIntent();
finish();
startActivity(intent);
11'den önceki API için repreate () kullanamazsınız. Bu şekilde çözdüm:
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
ve onCreate'de ..
@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
}
Zencefilli çörek aletini aradıktan sonra recreate, aşağıdaki kodları kullanmak istiyorum (zencefilli kurabiye için):
activity.mMainThread.mAppThread.scheduleRelaunchActivity(activity.mToken, null, null, 0, false, null);
Bu kodlar için, daha yüksek api'deki uygulamadandır.
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'da requestRelaunchActivity yok, ancak farktan şunu buldum:
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);
}
Bu yüzden scheduleRelaunchActivityyerine kullanabileceğimi düşünüyorum requestRelaunchActivity.
Ve bunları reflekte kullanarak yazdım:
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);
}
}
Bu kodları xposed çerçevesinin geri taşınması için kullanıyorum.
Build.VERSION_CODES.ECLAIR_MR1(v7) ile geriye doğru uyumlu . Eski sürümlerde de çalışabilir.
Eğer sorununuz buysa, Aktivitenizi doldurmak için muhtemelen başka bir yol uygulamalısınız. Yeniden çalıştırmak yerine, onCreate()onu onCreate()doldurma yönteminizi bazı argümanlarla çağırmalısınız. Veriler değiştiğinde, doldurma yöntemi başka bir argümanla çağrılmalıdır.
Bunu çözme şeklim Fragments kullanmaktı . Bunlar, destek kitaplığı kullanılarak API 4'e kadar geriye dönük uyumludur.
İçinde FrameLayout bulunan bir "sarmalayıcı" düzeni yaparsınız.
Misal:
<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>
Ardından istediğiniz zaman FrameLayout'u değiştirebileceğiniz bir FragmentActivity oluşturursunuz.
Misal:
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();
}
Şişirdiğiniz / değiştirdiğiniz Fragment'te onStart ve onCreateView'i normalde bir etkinliğin onCreate'ini kullanacağınız gibi kullanabilirsiniz.
Misal:
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();
}
}
Bir keresinde, firebase bulut depolamasını kullanarak veritabanı dosyasını yükleyen, silen ve ardından yeniden indiren bir test uygulaması yaptım. Verileri veritabanında görüntülemek için bulduğum tek çözüm aşağıdaki koddu. Bu durumda recreate()ne finish()işe yaradı ne de çalıştı.
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);
Veri değiştiğinde Parçanızı yenilemenin en iyi yolunu buldum
bir düğme "arama" varsa, düğmenin içindeki ARRAY listenizi başlatmanız gerekir
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 () 'e bir parametre iletmek istiyorsanız, fazladan ekleyerek yeni bir amaç oluşturmanız ve onunla StartActivity'yi çağırmanız gerekir. İşte bu şekilde yaptığım basit bir örnek.
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);
}
Sadece görüşünüzü yeniden yapmak istiyorsanız, aynı sorunu yaşadım. In onResumefonksiyonu bu koymayı deneyin:
mView = new AndroidPinballView(getApplication());
Bu da benim içindi onCreate(), bu yüzden bunu benim için onResumeişe yaradı :)