প্রোগ্রামিয়ালি পুনরায় চালু / কোনও ক্রিয়াকলাপ পুনরায় তৈরি করবেন?


121

আমি আমার ডাটাবেসে কিছু পরিবর্তন করার পরে, যার সাথে আমার দৃষ্টিভঙ্গিতে উল্লেখযোগ্য পরিবর্তন জড়িত, আমি আবার অঙ্কন করতে চাই, অনক্রিট পুনরায় সম্পাদন করতে চাই।

কীভাবে সম্ভব?

উত্তর:


129

আপডেট : অ্যান্ড্রয়েড এসডিকে 11 recreate()ক্রিয়াকলাপগুলিতে একটি পদ্ধতি যুক্ত করেছে ।


ক্রিয়াকলাপ শুরু হওয়া অভিপ্রায়টিকে কেবল পুনরায় ব্যবহার করে আমি এটি করেছি। starterIntentআপনার শ্রেণিতে একটি অভিপ্রায় নির্ধারণ করুন এবং এটি onCreate()ব্যবহারের জন্য নির্ধারণ করুন starterIntent = getIntent();। তারপরে আপনি যখন ক্রিয়াকলাপটি পুনরায় চালু করতে চান, কল করুনfinish(); startActivity(starterIntent);

এটি খুব মার্জিত সমাধান নয়, তবে এটি আপনার ক্রিয়াকলাপটি পুনরায় চালু করার এবং এটি সবকিছু পুনরায় লোড করতে বাধ্য করার এক সহজ উপায়।


8
আসলে আমি মনে করি যখন ডিভাইস ওরিয়েন্টেশনটি ক্রিয়াকলাপের oncreate পরিবর্তন করে একইভাবে ডাকা হয় .. সুতরাং আমি এটি করতে আপত্তি করি না। startActivity (getIntent ()); শেষ ();
রাজা

এটি স্টার্টঅ্যাক্টিভিটি (getIntent ()) করা স্মার্ট নয় কারণ এটি কেবলমাত্র কার্যক্রমের শীর্ষে ক্রিয়াকলাপগুলি স্তর করবে। পুরানো ক্রিয়াকলাপটি শেষ করা দরকার
ফলেনেরেপার

8
@ ফ্যালেনেরেপারেকে ঠিক সেই কারণেই finish()তত্ক্ষণাত্ ফোন করার পরামর্শ দিয়েছিলাম startActivity()...
স্টিভ হ্যালি

7
আমি finish();তখন এটি প্রথমে কল করে অর্জন করেছিstartActivity(starterIntent);
কার্লো রদ্রিগেজ

3
তাহলে এটি কোনটি? শেষ () এবং তারপরে স্টার্টএটিভিটি? কাছাকাছি বা অন্যান্য উপায়?
জেফ প্যাজেট

92

ক্রিয়াকলাপটি পুনরায় তৈরি করার পদ্ধতিটি কল করুন ।


19
এটি ঠিক আছে যদি আপনার অ্যাপ্লিকেশনটি কেবলমাত্র এসডিকে স্তর 11 এবং তারপরের উপরে লক্ষ্য করে চলেছে। নইলে আমি স্টিভ হ্যালের পদ্ধতির সাথে যাব।
টকলিটল

1
দুর্ভাগ্যক্রমে এটি কেবল মধুযন্ত্র ডিভাইস এবং তার উপর উপলব্ধ।
ইগোরগানাপলস্কি

2
যেখানে পুনরায় তৈরি করার পদ্ধতিটি কল করতে পারেন
SAndroidD

1
পুনরায় পদ্ধতিতে কলটি পুনরায় চতুর্দিকে অ্যাপটি বন্ধ করুন
SAndroidD

আমি ব্যবহার করতাম recreate()তবে এখন আমি একটি অদ্ভুত সমস্যা দেখতে পাচ্ছি যেখানে পুনরায় পুনরুদ্ধার করার সময় রেডিও বোতামগুলি রিসেট হয় না, তবে তারা যখন তখন finish(); startActivity(getIntent());ব্যবহার করে তখন এটি করে এবং পরবর্তী দিন বা সপ্তাহগুলিতে এটি কীভাবে কাজ করে তা দেখুন।
বেন

35

এখানে কয়েকটি উত্তর মিলিয়ে আপনি নীচের মতো কিছু ব্যবহার করতে পারেন।

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

পরীক্ষামূলক

আমি এটি কিছুটা পরীক্ষা করে দেখেছি এবং কিছু সমস্যা আছে:

  1. যদি স্ট্যাকের মধ্যে ক্রিয়াকলাপটি সর্বনিম্ন হয় তবে কলিংটি startActivity(...); finish();কেবলমাত্র অ্যাপ্লিকেশনটি উপস্থিত রয়েছে এবং কার্যকলাপটি পুনরায় আরম্ভ করবেন না
  2. super.recreate()ক্রিয়াকলাপটি পুরোপুরি পুনরুদ্ধার করার মতো আসলে কাজ করে না। এটি ডিভাইসটি ঘোরানোর সমতুল্য তাই আপনার যদি তাদের Fragmentসাথে থাকে setRetainInstance(true)তবে সেগুলি পুনরায় তৈরি করা হবে না; কেবল বিরতি দিয়ে আবার চালু করা হয়েছে।

সুতরাং বর্তমানে আমি বিশ্বাস করি না একটি গ্রহণযোগ্য সমাধান আছে।


5
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMBপরিবর্তে ব্যবহার করার জন্য11
এস.থিগনগেন

4
১১ টি অনমনীয়, .HONEYCOMB ঠিক নয়, কারণ আপনার এসডিকে <11 জানেন না wtat জানেন HONEYCOMB।
তপা সংরক্ষণ করুন

6
প্রতিস্থাপন startActivity(getIntent());finish();করতেfinish();startActivity(getIntent());
আহমেদ হামদি

না, সুপারিশ অনুসারে আপনার সর্বাধিক উপলভ্য এসডকে লক্ষ্য করা উচিত, সুতরাং মধুচক্রগুলি সংকলনের সময় উপলব্ধ হবে এবং আপনার অ্যাপ্লিকেশনটির অভ্যন্তরীণ ধ্রুবকটি বহন করা হবে। আমি বিশ্বাস করি যে ন্যূনতম এসডিকে ইন্টের চেয়ে বেশি এসডিডি ইন্ট ব্যবহার করা সাধারণ প্যাটার্ন।
হাই ঝাং

32

বিকল্প 1

কল করুন recreate()আপনার এর উপর Activity। তবে এই পদ্ধতিটির ফলে পুনর্নির্মাণের ক্রিয়াকলাপের সময় একটি ঝলকানি কালো পর্দা উপস্থিত হতে পারে।

বিকল্প 2

finish();
startActivity(getIntent());

এখানে কোনও "ঝলকানি" কালো পর্দা নেই, তবে আপনি পুরানো এবং নতুন দৃষ্টান্তগুলির মধ্যে একটি অতি-সুন্দর-সুন্দর কালো ব্যাকগ্রাউন্ড সহ একটি রূপান্তর দেখতে পাবেন। আমরা আরও ভাল করতে পারি

বিকল্প 3

এটি ঠিক করার জন্য, আমরা এতে একটি কল যুক্ত করতে পারি overridePendingTransition():

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

বিদায় কালো পর্দা, তবে আমার ক্ষেত্রে আমি এখনও রঙিন ব্যাকগ্রাউন্ডে এক ধরণের রূপান্তর (একটি বিবর্ণ অ্যানিমেশন) দেখতে পাচ্ছি। এটি কারণ যে আপনি নতুনটি তৈরি হওয়ার আগে এবং সম্পূর্ণ দৃশ্যমান হওয়ার আগে আপনি আপনার ক্রিয়াকলাপের বর্তমান উদাহরণটি শেষ করছেন , এবং আন্তঃস্থল রঙটি windowBackgroundথিমের বৈশিষ্ট্যের মান ।

বিকল্প 4

startActivity(getIntent());
finish();

finish() পরে কল করাstartActivity() ক্রিয়াকলাপগুলির মধ্যে ডিফল্ট রূপান্তরটি ব্যবহার করবে, প্রায়শই সামান্য স্লাইড-এনিমেশন সহ। তবে রূপান্তরটি এখনও দৃশ্যমান।

বিকল্প 5

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

আমার কাছে এটি সর্বোত্তম সমাধান কারণ এটি কোনও দৃশ্যমান স্থানান্তর ছাড়াই ক্রিয়াকলাপটি পুনঃসূচনা করে, যেমন কিছু না ঘটলে।

এটি কার্যকর হতে পারে যদি, উদাহরণস্বরূপ, আপনার অ্যাপ্লিকেশনটিতে আপনি সিস্টেমের ভাষার থেকে আলাদাভাবে ডিসপ্লে ল্যাঙ্গুয়েজ পরিবর্তনের কোনও উপায় প্রকাশ করেন। এই ক্ষেত্রে, ব্যবহারকারী যখনই আপনার অ্যাপ্লিকেশনটির ভাষা পরিবর্তন করে আপনি সম্ভবত ভাষাটি স্যুইচ করে তাত্ক্ষণিকভাবে চেহারা তৈরি করে, স্থানান্তর ছাড়াই আপনার ক্রিয়াকলাপটি আবার শুরু করতে চাইবেন।


1
বিকল্প 5-এ সমস্যা হ'ল এটি পূর্ববর্তী ক্রিয়াকলাপটি ব্যাকস্ট্যাকটিতে যুক্ত করে। এটিকে বেশ কয়েকবার কল করুন এবং আপনার ব্যবহারকারীকে আসল পূর্ববর্তী পৃষ্ঠায় যেতে বেশ কয়েকবার ফিরে ক্লিক করতে হবে।
অলি 24'19

23

যখন আমার কোনও ক্রিয়াকলাপ পুনরায় চালু করতে হবে তখন আমি নিম্নলিখিত কোডটি ব্যবহার করি। যদিও এটি সুপারিশ করা হয় না।

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

1
খুব পরিষ্কার এবং মার্জিত সমাধান। প্রাক-sdk 11 ডিভাইসে দুর্দান্ত কাজ করে।
ইগোরগানাপলস্কি

সুপার.ক্রিয়েট () পদ্ধতিতে সমস্যা ছিল, তবে এটি ললিপপ

6

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

}

3

জিঞ্জারব্রেড কার্যকর করার জন্য সন্ধান করার পরে 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)। এটি পুরানো সংস্করণগুলিতেও কাজ করতে পারে।
টিম কুক

3

recreate() আপনি যেখান থেকে আপনার ক্রিয়াকলাপটি পুনরায় তৈরি করতে চান সেই পদ্ধতিতে কল করুন । এই পদ্ধতিটি ক্রিয়াকলাপের বর্তমান উদাহরণটি ধ্বংস করে onDestroy()এবং এর সাথে ক্রিয়াকলাপ পুনরায় তৈরি করবে onCreate()


1

এটি যদি আপনার সমস্যা হয় তবে আপনার ক্রিয়াকলাপটি ভিউ পূরণের জন্য সম্ভবত অন্য কোনও উপায় প্রয়োগ করা উচিত। পুনরায় চলার পরিবর্তে আপনার onCreate()এটি করা উচিত যাতে onCreate()কিছু যুক্তি সহ আপনার ফিলিং পদ্ধতিটি কল হয়। যখন ডেটা পরিবর্তন হয়, ফিলিং পদ্ধতিটি অন্য একটি যুক্তি দিয়ে কল করা উচিত।


1

আমি যেভাবে সমাধান করেছি তা হল খণ্ডগুলি ব্যবহার করে । সমর্থন লাইব্রেরি ব্যবহার করে এপিআই 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();
    }
}

1

এছাড়াও আপনার পরিস্থিতির উপর নির্ভর করে আপনার ন্যায়বিচারের getActivity().recreate();পরিবর্তে প্রয়োজন হতে পারে recreate()

উদাহরণস্বরূপ, আপনি যদি recreate()শ্রেণীর ক্রিয়াকলাপের ভিতরে তৈরি করা ক্লাসে করছেন তবে এটি ব্যবহার করা উচিত ।


0

আমি একবার একটি পরীক্ষামূলক অ্যাপ্লিকেশন তৈরি করেছি যা ফায়ারবেস ক্লাউড স্টোরেজ ব্যবহার করে ডেটাবেস ফাইলটি পুনরায় ডাউনলোড করে, মুছে ফেলে। ডাটাবেসে ডেটা প্রদর্শন করতে, নিম্নলিখিত কোডটিই কেবলমাত্র আমার সমাধান খুঁজে পেয়েছিল। আমরাও recreate()না finish()এই ক্ষেত্রে কাজ করেন।

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

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

    }

-2

আপনি যদি অনক্রিট () তে একটি প্যারামিটারটি পাস করতে চান তবে আপনাকে অতিরিক্ত যুক্ত করে একটি নতুন অভিপ্রায় তৈরি করতে হবে এবং এটির সাথে স্টার্টএকটিভিটি কল করতে হবে। এখানে আমি একটি সহজ উদাহরণ যা এইভাবে ব্যবহার করেছি।

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

খারাপ নামকরণ কনভেনশন, খারাপ ভেরিয়েবলের নাম, সত্যই বিভ্রান্তিকর কোড ... -1
আহমেদ আদেল ইসমাইল

-4

আপনি যদি কেবল নিজের দৃষ্টিভঙ্গিটি আবার করতে চান তবে আমার ঠিক একই সমস্যা ছিল। onResumeফাংশনে এটি রাখার চেষ্টা করুন:

mView = new AndroidPinballView(getApplication());

এটি আমার মধ্যেও ছিল onCreate(), তাই এটি আমার জন্য কাজটিতে রেখে দেওয়া onResume:)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.