ওরিয়েন্টেশন পরিবর্তনের মাধ্যমে অ্যান্ড্রয়েড ফ্রেগমেন্ট লাইফসাইকেল


120

সামঞ্জস্যতা প্যাকেজটি ব্যবহার করে ফ্র্যাগমেন্টগুলি ব্যবহার করে ২.২ লক্ষ্য করুন to

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

ওরিয়েন্টেশন পরিবর্তনগুলি থেকে লগগুলি অদ্ভুত, টুকরা অনক্রিয়েটভিউতে একাধিক কল রয়েছে with

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

দয়া করে এখানে আমি কী ভুল করছি সে সম্পর্কে কেউ আলোকপাত করতে পারেন। ধন্যবাদ

ওরিয়েন্টেশন পরিবর্তনের পরে লগটি নিম্নরূপ।

Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null


Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null


Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null

প্রধান ক্রিয়াকলাপ (ফ্র্যাগমেন্টএটিভিটি)

public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */

private static final String TAG = "FragmentTest.FragmentTestActivity";


FragmentManager mFragmentManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Log.d(TAG, "onCreate");

    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
}

এবং খণ্ড

public class FragmentOne extends Fragment {

private static final String TAG = "FragmentTest.FragmentOne";

EditText mEditText;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    Log.d(TAG, "OnCreateView");

    View v = inflater.inflate(R.layout.fragmentonelayout, container, false);

    // Retrieve the text editor, and restore the last saved state if needed.
    mEditText = (EditText)v.findViewById(R.id.editText1);

    if (savedInstanceState != null) {

        Log.d(TAG, "OnCreateView->SavedInstanceState not null");

        mEditText.setText(savedInstanceState.getCharSequence("text"));
    }
    else {
        Log.d(TAG,"OnCreateView->SavedInstanceState null");
    }
    return v;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Log.d(TAG, "FragmentOne.onSaveInstanceState");

    // Remember the current text, to restore if we later restart.
    outState.putCharSequence("text", mEditText.getText());
}

স্পষ্ট

<uses-sdk android:minSdkVersion="8" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:label="@string/app_name"
        android:name=".activities.FragmentTestActivity" 
        android:configChanges="orientation">
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

এটি সঠিক উত্তর কিনা তা আমি জানি না, তবে টুকরো যোগ করার সময় একটি ট্যাগ ব্যবহার করার চেষ্টা করুন, (R.id.fragment_container, "MYTAG") যোগ করুন, বা ব্যর্থ হয়ে, প্রতিস্থাপন করুন (R.id.fragment_container, খণ্ড, "MYTAG) ")
জেসন

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

উত্তর:


189

আপনি আপনার টুকরোটিকে অন্যের উপরে রাখছেন।

যখন কোনও কনফিগার পরিবর্তন ঘটে তখন পুরানো টুকরাটি নতুন ক্রিয়াকলাপে পুনরায় তৈরি করা হলে নিজেকে যুক্ত করে। এটি বেশিরভাগ সময় পিছনে একটি ব্যথা হয়।

আপনি নতুন ফ্রিক্রিটিংয়ের পরিবর্তে একই টুকরোটি ব্যবহার করে ত্রুটিগুলি থামাতে পারেন। কেবল এই কোডটি যুক্ত করুন:

if (savedInstanceState == null) {
    // only create fragment if activity is started for the first time
    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
} else {        
    // do nothing - fragment is recreated automatically
}

সতর্কতা অবলম্বন করুন: আপনি যদি চেষ্টা করেন এবং খণ্ডের অভ্যন্তর থেকে ক্রিয়াকলাপের দর্শনগুলি অ্যাক্সেস করেন তবে লাইফ সাইকেলের পরিবর্তন হবে t (কোনও খণ্ড থেকে পিতামাতার ক্রিয়াকলাপের থেকে দর্শন পাওয়া সহজ নয়)।


54
"বেশিরভাগ সময় পিছনে এটি একটি ব্যথার ব্যথা" (থাম্বস আপ)
রাশিংজ

1
ফ্রেগমেন্টস্টেটপেজারএডাপ্টারের সাথে ভিউপেজ ব্যবহারের ক্ষেত্রে কীভাবে একই পরিস্থিতি পরিচালনা করা যায় ... কোনও পরামর্শ?
CoDe

5
অফিসিয়াল ডকুমেন্টেশনে কি একইরকম দাবি রয়েছে? এই কি গাইডে বর্ণিত যে একটি অসঙ্গতি নয়: "when the activity is destroyed, so are all fragments"? যেহেতু "When the screen orientation changes, the system destroys and recreates the activity [...]"
সিউরাস 19

4
সাইরাস - না, ক্রিয়াকলাপটি প্রকৃতপক্ষে ধ্বংস হয়ে গেছে, এতে থাকা খণ্ডগুলি কেবলমাত্র ক্রিয়াকলাপ থেকে নয়, ফ্রেগমেন্টম্যানেজারে উল্লেখ করা হয়, তাই এটি অবশেষে এবং পুনরায় যুক্ত করা হয়।
গ্রামীণ

4
ফ্রেগমেন্টম্যানেজারে সন্ধান করার পরে ক্রেট এবং অনডাস্ট্রয়ে পদ্ধতিগুলির পাশাপাশি এর হ্যাশকোডগুলিতে লগিংয়ের টুকরোটি পরিষ্কারভাবে দেখায় যে খণ্ডটি নষ্ট হয়ে গেছে। এটি কেবল পুনরায় তৈরি করা হয়েছে এবং স্বয়ংক্রিয়ভাবে পুনরায় সংযুক্ত। কেবলমাত্র যদি আপনি তৈরির পদ্ধতিতে পুনরায় ইনস্টল (সত্য) স্থাপন করেন তবে এটি সত্যই ধ্বংস হবে না
Lemao1981

87

এই বইয়ের উদ্ধৃতি দিতে দেওয়ার জন্য, "একটি সামঞ্জস্যপূর্ণ ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করতে, অ্যান্ড্রয়েড ফ্রেগমেন্ট লেআউটটি ধরে রাখে এবং যখন কোনও কনফিগারেশন পরিবর্তনের কারণে কোনও ক্রিয়াকলাপ পুনরায় শুরু করা হয় তখন যুক্ত ব্যাক স্ট্যাক যুক্ত থাকে।" (পৃষ্ঠা 124)

এবং এর কাছে যাওয়ার উপায়টি হ'ল প্রথমে খন্ডটি ব্যাক স্ট্যাকটি ইতিমধ্যে পপুলেটেড হয়েছে কিনা তা পরীক্ষা করে দেখানো এবং নতুন খণ্ডের উদাহরণটি তৈরি করা কেবল যদি তা না করে থাকে:

@Override
public void onCreate(Bundle savedInstanceState) {

        ...    

    FragmentOne fragment = (FragmentOne) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) {
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container, new FragmentOne());
        fragmentTransaction.commit();
    }
}

2
আপনি সম্ভবত এই এক দিয়ে আমাকে অনেক সময় বাঁচিয়েছেন ... অনেক অনেক ধন্যবাদ আপনি এই উত্তরটি গ্র্যামের সাথে একটির সাথে সংযুক্ত করতে পারেন কনফিগার পরিবর্তনগুলি এবং টুকরোগুলি পরিচালনা করার জন্য নিখুঁত সমাধান পেতে।
আজপাবলিক

10
এটি আসলে সঠিক উত্তর, চিহ্নিত উত্তর নয়। আপনাকে অনেক ধন্যবাদ!
উরিয়েল ফ্রাঙ্কেল

ভিউপ্যাজার টুকরা বাস্তবায়নের ক্ষেত্রে কীভাবে একই পরিস্থিতি পরিচালনা করা যায়।
CoDe

এই ছোট্ট রত্নটি এমন একটি সমস্যায় সহায়তা করেছিল যা আমি বেশ কয়েক দিন ধরে দেখছিলাম। ধন্যবাদ! এটি অবশ্যই সমাধান।
আপনারা কে কে

1
@ শার্পেজেজ আপনার যদি একাধিক টুকরো থাকে তবে ধারকগুলিতে যুক্ত করার সময় আপনার সেগুলি ট্যাগ দেওয়া উচিত, এবং তারপরে রেফারেন্স পেতে mFraamentManager.findFragmentByTag (FindFraamentById এর পরিবর্তে) ব্যবহার করুন - এভাবে আপনি প্রতিটি খণ্ডের শ্রেণিটি জানতে পারবেন এবং সক্ষম হবেন সঠিকভাবে কাস্ট করুন
k29

10

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

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState==null) {
        //do your stuff
    }
}

খণ্ডগুলি অবশ্যই অপরিবর্তিত হওয়া উচিত।


আমরা কী জানি খণ্ডটি তৈরি এবং যুক্ত হওয়ার পরে উদাহরণটি সংরক্ষণ করা হবে? আমি হ্যাট বলতে চাইছি যদি কোনও ফ্র্যাগমেন্ট যোগ হওয়ার ঠিক আগে কোনও ব্যবহারকারী ঘোরে? আমাদের এখনও নন-নাল সেভড ইনস্ট্যান্স স্টেট থাকবে যাতে এতে খণ্ডিত রাজ্য নেই
ফরিদ

4

আপনি @Overrideব্যবহার করে ফ্র্যাগমেন্টএটিভিটি করতে পারেন onSaveInstanceState()super.onSaveInstanceState()পদ্ধতিতে কল না নিশ্চিত করুন ।


2
এটি সম্ভবত ইতিমধ্যে এই অগোছালো প্রক্রিয়াতে আরও সম্ভাব্য সমস্যাগুলির পরিচয়দানকারী ক্রিয়াকলাপগুলি ভেঙে দেবে। ফ্র্যাগমেন্টএটিভিটির উত্স কোডটি দেখুন: এটি সেখানে সমস্ত খণ্ডের রাজ্যগুলি সংরক্ষণ করছে।
ব্রায়ান

আমার সমস্যা ছিল যে আমার বিভিন্ন ভিন্ন অভিযোজনের জন্য আলাদা অ্যাডাপ্টারের গণনা রয়েছে। সুতরাং ডিভাইসটি চালু করার পরে এবং কিছু পৃষ্ঠা সোয়াইপ করার পরে আমার সর্বদা একটি অদ্ভুত পরিস্থিতি ছিল, আমি পুরানো এবং ভুলটি পেয়েছি। সেভডইনস্ট্যান্স ঘুরিয়ে এটি মেমরি ফাঁস ছাড়াই সবচেয়ে ভাল কাজ করে (আমি সেটসেভডএনেবলড (মিথ্যা) befor ব্যবহার করেছি এবং প্রতিটি ওরিয়েন্টেশন পরিবর্তনে বড় মেমরি ফাঁস দিয়ে শেষ করেছি)
ইনফরম্যাটিক 0

0

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

public static class DetailsActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getResources().getConfiguration().orientation
            == Configuration.ORIENTATION_LANDSCAPE) {
            // If the screen is now in landscape mode, we can show the
            // dialog in-line with the list so we don't need this activity.
            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.
            DetailsFragment details = new DetailsFragment();
            details.setArguments(getIntent().getExtras());
            getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
        }
    } 
}

0

কনফিগারেশন পরিবর্তনে, ফ্রেমওয়ার্কটি আপনার জন্য খণ্ডটির একটি নতুন উদাহরণ তৈরি করবে এবং এটিকে ক্রিয়াকলাপে যুক্ত করবে। সুতরাং এর পরিবর্তে:

FragmentOne fragment = new FragmentOne();

fragmentTransaction.add(R.id.fragment_container, fragment);

এটা কর:

if (mFragmentManager.findFragmentByTag(FRAG1_TAG) == null) {
    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment, FRAG1_TAG);
}

দয়া করে নোট করুন যে ফ্রেমওয়ার্কটি ওরিয়েন্টেশন পরিবর্তনে ফ্রেগমেন্টঅন এর একটি নতুন উদাহরণ যুক্ত করে যদি না আপনি সেটট্রেটইনস্ট্যান্স (সত্য) না কল করেন, তবে সেক্ষেত্রে এটি ফ্রেগমেন্টঅন-এর পুরানো দৃষ্টান্ত যুক্ত হবে।


-1

আপনি যদি কেবল একটি প্রকল্প করেন তবে প্রকল্প পরিচালক বলেছেন যে আপনাকে স্যুইচিং ফাংশন স্ক্রিন অর্জন করতে হবে, তবে আপনি স্ক্রিন স্যুইচিং লোডকে আলাদা আলাদা লেআউট (লেআউট এবং লেআউট-পোর্ট সিস্টেম তৈরি করতে পারবেন না) চান না।

আপনি স্বয়ংক্রিয়ভাবে স্ক্রিনের অবস্থা নির্ধারণ করবেন, সংশ্লিষ্ট লেআউটটি লোড করবেন), ক্রিয়াকলাপ বা খণ্ডটি পুনরায় শুরু করার প্রয়োজনের কারণে ব্যবহারকারীর অভিজ্ঞতা ভাল নয়, সরাসরি স্ক্রিন সুইচে নয়, আমি উল্লেখ করছি? Url = YgNfP-vHy-Nuldi7YHTfNet3AtLdN-w__O3z1wLOnzr3wDjYo7X7PYdNyhw8R24ZE22xiKnydni7R0r35s2fOLcHOiLGYT9Qh_fjqtytJki & WD = & eqid = f258719e0001f24000000004585a1082

ভিত্তিটি হ'ল লেআউট_ ওয়েটের লেআউটের উপায়ের ওজনকে আপনার লেআউটটি নিম্নরূপ ব্যবহার করে:

<LinearLayout
Android:id= "@+id/toplayout"
Android:layout_width= "match_parent"
Android:layout_height= "match_parent"
Android:layout_weight= "2"
Android:orientation= "horizontal" >

সুতরাং আমার দৃষ্টিভঙ্গিটি হল, যখন স্ক্রিনটি স্যুইচ করা হচ্ছে, ভিউ ফাইলের নতুন লেআউটটি লোড করার দরকার নেই, onCfigrationChanged গতিশীল ওজনে লেআউটটি পরিবর্তন করুন, নিম্নলিখিত পদক্ষেপগুলি: 1 প্রথম সেট: ক্রিয়াকলাপের বৈশিষ্ট্যে অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল: অ্যান্ড্রয়েড: কনফিগারচেনজ = "কীবোর্ডহিডান | ওরিয়েন্টেশন | স্ক্রিনসাইজ" স্ক্রিন স্যুইচিং প্রতিরোধ করতে, পুনরায় লোড করা এড়ান, যাতে অন-কনফিগারেশনচেনজড পদ্ধতিতে onCfigrationChanged 2 পুনর্লিখনের ক্রিয়াকলাপ বা খণ্ডে নজরদারি করতে সক্ষম হতে পারেন।

@Override
Public void onConfigurationChanged (Configuration newConfig) {
    Super.onConfigurationChanged (newConfig);
    SetContentView (R.layout.activity_main);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        //On the layout / / weight adjustment
        LinearLayout toplayout = (LinearLayout) findViewById (R.id.toplayout);
        LinearLayout.LayoutParams LP = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.0f);
        Toplayout.setLayoutParams (LP);
        LinearLayout tradespace_layout = (LinearLayout) findViewById(R.id.tradespace_layout);
        LinearLayout.LayoutParams LP3 = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.8f);
        Tradespace_layout.setLayoutParams (LP3);
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        //On the layout / / weight adjustment
        LinearLayout toplayout = (LinearLayout) findViewById (R.id.toplayout);
        LinearLayout.LayoutParams LP = new LayoutParams (LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.8f);
        Toplayout.setLayoutParams (LP);
        LinearLayout tradespace_layout = (LinearLayout) findViewById (R.id.tradespace_layout);
        LinearLayout.LayoutParams LP3 = new LayoutParams (LinearLayout.LayoutParams.MATCH_PARENT, 0, 2.0f);
        Tradespace_layout.setLayoutParams (LP3);
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.