जवाबों:
अद्यतन : एंड्रॉइड एसडीके 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()वास्तव में पूरी तरह से गतिविधि को फिर से बनाने के समान कार्य नहीं करता है। यह डिवाइस को घुमाने के बराबर है इसलिए यदि आपके पास कोई Fragmentएस है तो 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);
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);
इन कोडों के लिए, यह उच्च एपीआई में कार्यान्वयन से है।
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 का कोई अनुरोध नहीं है। हालांकि, इस अंतर से, मुझे यह पता चला:
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()कुछ तर्क के साथ आपके भरने की विधि को कॉल किया जा सके । जब डेटा बदलता है, तो भरने की विधि को किसी अन्य तर्क के साथ बुलाया जाना चाहिए।
जिस तरह से मैंने इसे हल किया वह फ्रेगमेंट्स का उपयोग करके है । समर्थन पुस्तकालय का उपयोग करके एपीआई 4 तक ये पीछे की ओर संगत हैं।
आप इसमें एक फ्रेम-आउट के साथ "रैपर" लेआउट बनाते हैं।
उदाहरण:
<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 को विच में बनाते हैं, आप किसी भी समय फ़्रेमलैटआउट को बदल सकते हैं।
उदाहरण:
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();
}
}
मैंने एक बार एक परीक्षण ऐप बनाया था जो फायरबेस क्लाउड स्टोरेज का उपयोग करके डेटाबेस फ़ाइल को अपलोड, डिलीट और फिर डाउनलोड करता है। डेटाबेस में डेटा प्रदर्शित करने के लिए, निम्नलिखित कोड एकमात्र समाधान था जो मुझे मिला। न तो recreate()है और न ही finish()इस मामले में काम किया।
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);
जब डेटा में बदलाव होता है तो मुझे आपके फ्रैगमेंट को ताज़ा करने का सबसे अच्छा तरीका पता चला
यदि आपके पास एक बटन "खोज" है, तो आपको बटन के अंदर अपनी ARRAY सूची को इनिशियलाइज़ करना होगा
mSearchBtn.setOnClickListener (नया दृश्य .nClickListener () {
@ ऑवरराइड सार्वजनिक शून्य पर क्लिक करें (देखें 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मेरे लिए काम में लाना :)