উত্তর:
আপডেট : অ্যান্ড্রয়েড এসডিকে 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 এর আগে API এর জন্য আপনি পুনরায় তৈরি করতে পারবেন না ()। আমি এইভাবে সমাধান করেছি:
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
এবং অনক্রিটেতে ..
@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);
}
এপিআই -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);
}
}
আমি এক্সপোজড ফ্রেমওয়ার্কের ব্যাক-পোর্টিংয়ের জন্য এই কোডগুলি ব্যবহার করছি।
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>
তারপরে আপনি ফ্রেমলয়আউটটি যে কোনও সময় প্রতিস্থাপন করতে পারবেন যা আপনি ফ্র্যাগমেন্টএকটিভিটি তৈরি করুন।
উদাহরণ:
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();
}
খণ্ডে আপনি স্ফীত / প্রতিস্থাপন করতে পারেন তবে আপনার মতো অন স্টার্ট এবং অনক্রেটভিউ ব্যবহার করতে পারেন সাধারণভাবে কোনও ক্রিয়াকলাপের অনক্রিট ব্যবহার করতে পারেন।
উদাহরণ:
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);
ডেটা পরিবর্তন হলে আমি আপনার টুকরোটি রিফ্রেশ করার সর্বোত্তম উপায় খুঁজে পেয়েছি
আপনার যদি একটি বোতাম "অনুসন্ধান" থাকে তবে আপনাকে বোতামের অভ্যন্তরে আপনার এআরএআই তালিকা শুরু করতে হবে
mSearchBtn.setOnClickListener (নতুন View.OnClickListener () {
@ ওভাররাইড পাবলিক শূন্য অনক্লিক (ভি দেখুন) {
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 );
}
আপনি যদি অনক্রিট () তে একটি প্যারামিটারটি পাস করতে চান তবে আপনাকে অতিরিক্ত যুক্ত করে একটি নতুন অভিপ্রায় তৈরি করতে হবে এবং এটির সাথে স্টার্টএকটিভিটি কল করতে হবে। এখানে আমি একটি সহজ উদাহরণ যা এইভাবে ব্যবহার করেছি।
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:)