ফ্রেগমেন্টপেজারএডাপ্টার ব্যবহার করার সময় কীভাবে বিদ্যমান টুকরো পাওয়া যায়


102

আমি সমস্যা আমার টুকরা মাধ্যমে একে অপরের সাথে যোগাযোগ উপার্জন আছে Activity, যা ব্যবহার করা হয় FragmentPagerAdapterএকটি সাহায্যকারী শ্রেণী হিসেবে, যে কার্যকরী ট্যাবগুলির ব্যবস্থাপনা এবং একটি সংযোগ সমস্ত বিবরণ ViewPagerযুক্ত সঙ্গে TabHostFragmentPagerAdapterঅ্যান্ড্রয়েড নমুনা প্রকল্প সাপোর্ট 4 ডেমোস যেমন সরবরাহ করেছে ঠিক তেমনই আমি প্রয়োগ করেছি

মূল প্রশ্নটি হল আমার FragmentManagerযখন আইডি বা ট্যাগ না থাকে তখনই আমি কীভাবে নির্দিষ্ট টুকরোটি পেতে পারি? FragmentPagerAdapterআইডি এবং ট্যাগগুলিকে টুকরো টুকরো করে তৈরি করছে এবং স্বয়ংক্রিয় উত্পাদন করছে।



@ জে কে 2 কে এটি কীভাবে 1 বছরের পরে জিজ্ঞাসা করা প্রশ্নটির নকল হতে পারে
ডেভি

@ দায়িত লেবেলের মতো সদৃশ, সময়ের সাথে সম্পর্কিত নয়, পরে প্রশ্নগুলির উচ্চতর মতামত রয়েছে
jk2K

উত্তর অধিকাংশই এখানে এত আমার উত্তর চেক উৎপাদনে কাজ করে না, stackoverflow.com/a/54280113/2413303
EpicPandaForce

উত্তর:


194

সমস্যার সংক্ষিপ্তসার

দ্রষ্টব্য: এই উত্তরে আমি রেফারেন্স FragmentPagerAdapterএবং এর উত্স কোড যাচ্ছি । তবে সাধারণ সমাধানটিও প্রয়োগ করা উচিত FragmentStatePagerAdapter

আপনি যদি এটি পড়েন তবে আপনি সম্ভবত জানেন যে FragmentPagerAdapter/ আপনার FragmentStatePagerAdapterজন্য তৈরি করা Fragmentsহয়েছিল ViewPager, তবে ক্রিয়াকলাপের বিনোদন (কোনও ডিভাইস রোটেশন বা মেমরি ফিরে পেতে আপনার অ্যাপ্লিকেশনটিকে মেরে ফেলা সিস্টেম থেকে) সেগুলি Fragmentsআর তৈরি করা হবে না, পরিবর্তে তাদের দৃষ্টান্ত থেকে উদ্ধার করাFragmentManager । এখন বলুন যে Activityএগুলিতে Fragmentsকাজ করার জন্য আপনার একটি রেফারেন্স পাওয়া দরকার। আপনার অভ্যন্তরীণভাবে সেট করুন কারণ এগুলি তৈরির জন্য আপনার কোনও idবা নেই । সুতরাং সমস্যাটি কীভাবে সেই তথ্য ছাড়াই তাদের একটি রেফারেন্স পাবেন ...tagFragmentsFragmentPagerAdapter

বর্তমান সমাধানগুলির সাথে সমস্যা: অভ্যন্তরীণ কোডের উপর নির্ভর করে

সমাধান আমি এই এবং অনুরূপ প্রশ্নে দেখা করেছি অনেক বিদ্যমান একটি রেফারেন্স পেয়ে উপর নির্ভর Fragmentকল করে FragmentManager.findFragmentByTag()এবং অনুকারী অভ্যন্তরীণভাবে নির্মিত ট্যাগ: "android:switcher:" + viewId + ":" + id। এটির সাথে সমস্যাটি হ'ল আপনি অভ্যন্তরীণ উত্স কোডের উপর নির্ভর করছেন যা আমরা সকলেই জানি যে চিরকাল একই থাকবে তার নিশ্চয়তা দেওয়া হয় না। গুগলের অ্যান্ড্রয়েড ইঞ্জিনিয়াররা সহজেই tagকাঠামোগত পরিবর্তন করার সিদ্ধান্ত নিতে পারে যা আপনার কোডটি ভেঙে দেবে যার ফলে আপনি বিদ্যমানটির কোনও রেফারেন্স খুঁজে পেতে পারেন না Fragments

অভ্যন্তরীণ উপর নির্ভর না করে বিকল্প সমাধান tag

এটির মাধ্যমে অভ্যন্তরীণ সেটটির উপর নির্ভর করে না যে কীভাবে Fragmentsফিরে আসে তার একটি রেফারেন্স কীভাবে পাবেন তার একটি সাধারণ উদাহরণ এখানে । কী ওভাররাইড হয় সেখানে এবং তথ্যসূত্র সংরক্ষণ পরিবর্তে এর মধ্যে ।FragmentPagerAdaptertagsFragmentsinstantiateItem()getItem()

public class SomeActivity extends Activity {
    private FragmentA m1stFragment;
    private FragmentB m2ndFragment;

    // other code in your Activity...

    private class CustomPagerAdapter extends FragmentPagerAdapter {
        // other code in your custom FragmentPagerAdapter...

        public CustomPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // Do NOT try to save references to the Fragments in getItem(),
            // because getItem() is not always called. If the Fragment
            // was already created then it will be retrieved from the FragmentManger
            // and not here (i.e. getItem() won't be called again).
            switch (position) {
                case 0:
                    return new FragmentA();
                case 1:
                    return new FragmentB();
                default:
                    // This should never happen. Always account for each position above
                    return null;
            }
        }

        // Here we can finally safely save a reference to the created
        // Fragment, no matter where it came from (either getItem() or
        // FragmentManger). Simply save the returned Fragment from
        // super.instantiateItem() into an appropriate reference depending
        // on the ViewPager position.
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            // save the appropriate reference depending on position
            switch (position) {
                case 0:
                    m1stFragment = (FragmentA) createdFragment;
                    break;
                case 1:
                    m2ndFragment = (FragmentB) createdFragment;
                    break;
            }
            return createdFragment;
        }
    }

    public void someMethod() {
        // do work on the referenced Fragments, but first check if they
        // even exist yet, otherwise you'll get an NPE.

        if (m1stFragment != null) {
            // m1stFragment.doWork();
        }

        if (m2ndFragment != null) {
            // m2ndFragment.doSomeWorkToo();
        }
    }
}

অথবা আপনি যদি tagsশ্রেণীর সদস্যের পরিবর্তনশীল / রেফারেন্সের পরিবর্তে কাজ করতে পছন্দ করেন তবে আপনি একই পদ্ধতিতে সেটটিও Fragmentsদখল করতে পারেন : দ্রষ্টব্য: এটি তৈরি করার সময় এটি সেট না হওয়ার কারণে এটি প্রযোজ্য নয় ।tagsFragmentPagerAdapterFragmentStatePagerAdaptertagsFragments

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
    // get the tags set by FragmentPagerAdapter
    switch (position) {
        case 0:
            String firstTag = createdFragment.getTag();
            break;
        case 1:
            String secondTag = createdFragment.getTag();
            break;
    }
    // ... save the tags somewhere so you can reference them later
    return createdFragment;
}

মনে রাখবেন যে এই পদ্ধতিটি অভ্যন্তরীণ tagসেটটি নকল করার উপর নির্ভর করে না FragmentPagerAdapterএবং পরিবর্তে তাদের পুনরুদ্ধারের জন্য যথাযথ এপিআই ব্যবহার করে। এইভাবে এমনকি tagভবিষ্যতের সংস্করণগুলির পরিবর্তনগুলি SupportLibraryআপনি এখনও নিরাপদ থাকবেন।


ভুলবেন না যে, আপনার নকশা উপর নির্ভর করে Activity, Fragmentsআপনি কাজ করতে পারে চেষ্টা করছেন বা করে যে জন্য এখনো অস্তিত্ব নাও থাকতে পারে, তাই আপনি অ্যাকাউন্টে nullআপনার রেফারেন্স ব্যবহার করার আগে চেক।

এছাড়াও, পরিবর্তে যদি আপনি কাজ করে যাচ্ছেন FragmentStatePagerAdapter, তবে আপনি কঠোর উল্লেখগুলি আপনার কাছে রাখতে চান না Fragmentsকারণ আপনার অনেকগুলি থাকতে পারে এবং কঠোর উল্লেখগুলি অযথা তাদের স্মৃতিতে রাখে। পরিবর্তে মানগুলির পরিবর্তে পরিবর্তনগুলিতে Fragmentরেফারেন্সগুলি সংরক্ষণ করুন WeakReference। এটার মত:

WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
    // reference hasn't been cleared yet; do work...
}

4
এই সত্যিই একটি ভাল সমাধান, কিন্তু এটা তার কার্যকারিতা হারাতে যদি আপনি জানেন না কত টুকরা পাস করা হবে না বলে মনে হয়।
দাঙ্গা যায় বুনন

4
@ জর্পিক্স আপনি একটি হ্যাশম্যাপে তৈরি টুকরো সংরক্ষণ করতে পারেন: মানচিত্র.পুট (অবস্থান, তৈরি ফ্রেম);
টম বেভল্যান্ডার

12
এটি চেকমার্কের দাবিদার! এটি সম্পাদন করার জন্য খুব চালাক এবং বিস্তৃত উপায়। আপনি আমাকে অনেক সাহায্য করেছেন ধন্যবাদ আপনাকে!
ইয়ং_সৌভালকি

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

4
কোন কিছু ওভাররাইড করতে হবে এবং আপনি আসলে করা উচিত নয় অগ্রাহ্য করা instantiateItem। এই কাজ করতে সঠিক ভাবে হয় কল instantiateItem মধ্যে onCreateপদ্ধতির আপনার কার্যকলাপের দ্বারা বেষ্টিত startUpdateএবং finishUpdate। বিশদ জন্য আমার উত্তর দেখুন
মোরগওয়াই

83

আমি নীচের পোস্টের উপর ভিত্তি করে আমার প্রশ্নের উত্তর পেয়েছি: খণ্ড খণ্ডের পুনরায় ব্যবহারের টুকরো পুনরায় ব্যবহার করে

আমি কিছু জিনিস শিখেছি:

  1. getItem(int position)মধ্যে FragmentPagerAdapterকি এই পদ্ধতি আসলে না হয় বরং বিভ্রান্তিকর নাম। এটি নতুন টুকরো তৈরি করে, বিদ্যমানগুলি ফেরত দেয় না returning এত অর্থ সহ, পদ্ধতিটি createItem(int position)অ্যান্ড্রয়েড এসডিকে এর মতো কিছুতে নামকরণ করা উচিত । সুতরাং এই পদ্ধতিটি আমাদের টুকরো টুকরো করতে সহায়তা করে না।
  2. পুরানো টুকরো টুকরো টুকরো টুকরো সম্পর্কে ফ্রেমপেইজারএডাপ্টারহোল্ডসের রেফারেন্সের ব্যাখ্যার ভিত্তিতে আপনার খণ্ডগুলির তৈরি ছেড়ে দেওয়া উচিত FragmentPagerAdapterএবং এর অর্থ হতে পারে আপনার খণ্ডগুলি বা তাদের ট্যাগগুলির কোনও রেফারেন্স নেই। আপনার কাছে যদি খণ্ড ট্যাগ থাকে তবে আপনি FragmentManagerকল করে সহজেই এর থেকে রেফারেন্স পেতে পারেন findFragmentByTag()। প্রদত্ত পৃষ্ঠায় অবস্থানে কোনও খণ্ডের ট্যাগ বের করার জন্য আমাদের একটি উপায় প্রয়োজন।

সমাধান

খণ্ড ট্যাগটি পুনরুদ্ধার করতে এবং findFragmentByTag()পদ্ধতিতে এটি প্রেরণ করতে আপনার ক্লাসে নিম্নলিখিত সহায়ক সাহায্যকারী পদ্ধতি যুক্ত করুন ।

private String getFragmentTag(int viewPagerId, int fragmentPosition)
{
     return "android:switcher:" + viewPagerId + ":" + fragmentPosition;
}

বিঃদ্রঃ! এটি অভিন্ন পদ্ধতি যা FragmentPagerAdapterনতুন খণ্ড তৈরি করার সময় ব্যবহার করে। এই লিঙ্কটি দেখুন http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FramentPagerAdapter.java#104


বিটিডব্লিউ, এই প্রশ্নোত্তর বিষয়ে আরও কিছু রয়েছে: স্ট্যাকওভারফ্লো
টমাস

4
ভিউআইডি ইনপুট প্যারামিটারটি কী? কোন ভিউ?
নীলজোর

@ নীলজার ভিউআইডি হ'ল ভিউপ্যাজারের আইডি।
ডাঃ জ্যাকি

ট্যাগটি অনুমান করার পরিবর্তে খণ্ডটি তার কার্যকলাপটিকে তার ট্যাগটি বলতে পারে onAttach()?
বেসিন

4
এটি সঠিক উপায় নয়। @ টনি চ্যান এর উত্তর সবচেয়ে ভাল এবং সঠিক উপায়।
মরতেজা রাস্টগু

17

ম্যানুয়ালি খণ্ডের ট্যাগ তৈরি করে আপনাকে instantiateItemঅভ্যন্তরীণ makeFragmentNameপদ্ধতির সাথে সামঞ্জস্যের উপর নির্ভর করতে বা ওভাররাইড করতে হবে না ।
instantiateItemএকটি হল পাবলিক পদ্ধতি যাতে আপনি করতে পারেন এবং আসলে উচিত এটা কল onCreateআপনার কার্যকলাপের পদ্ধতি কল দিয়ে বেষ্টিত startUpdateএবং finishUpdateবর্ণনা অনুযায়ী পদ্ধতি PagerAdapter javadoc :

পেজারআডাপ্টার পদ্ধতি স্টার্টআপডেট (ভিউগ্রুপ) -এর কল একটি ইঙ্গিত দেয় যে ভিউপ্যাজারের সামগ্রীগুলি পরিবর্তন হতে চলেছে। ইনস্ট্যান্টিয়েট আইটেম (ভিউগ্রুপ, ইনট) এবং / অথবা ডোনস্টাইম (ভিউগ্রুপ, ইনট, অবজেক্ট) এ এক বা একাধিক কলগুলি অনুসরণ করবে এবং একটি আপডেটের সমাপ্তি ফিনিসআপডেট (ভিউগ্রুপ) এর কল দ্বারা সিগন্যাল করা হবে।

তারপরে আপনি উপরের দিকের সাহায্যে আপনার প্রয়োজনের ভিত্তিতে স্থানীয় টুকরো টুকরো টুকরো টুকরো উল্লেখ করতে পারেন। উদাহরণ দেখুন:

public class MyActivity extends AppCompatActivity {

    Fragment0 tab0; Fragment1 tab1;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.myLayout);
        ViewPager viewPager = (ViewPager) findViewById(R.id.myViewPager);
        MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        ((TabLayout) findViewById(R.id.tabs)).setupWithViewPager(viewPager);

        adapter.startUpdate(viewPager);
        tab0 = (Fragment0) adapter.instantiateItem(viewPager, 0);
        tab1 = (Fragment1) adapter.instantiateItem(viewPager, 1);
        adapter.finishUpdate(viewPager);
    }

    class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager manager) {super(manager);}

        @Override public int getCount() {return 2;}

        @Override public Fragment getItem(int position) {
            if (position == 0) return new Fragment0();
            if (position == 1) return new Fragment1();
            return null;  // or throw some exception
        }

        @Override public CharSequence getPageTitle(int position) {
            if (position == 0) return getString(R.string.tab0);
            if (position == 1) return getString(R.string.tab1);
            return null;  // or throw some exception
        }
    }
}

instantiateItemপ্রথমে বিদ্যমান খণ্ডগুলির উদাহরণগুলির থেকে রেফারেন্স পাওয়ার চেষ্টা করবে FragmentManager। কেবলমাত্র সেগুলি এখনও উপস্থিত না থাকলে এটি getItemআপনার অ্যাডাপ্টার থেকে পদ্ধতি ব্যবহার করে নতুন তৈরি করে এবং সেগুলিতে "সঞ্চয়" করেFragmentManager ভবিষ্যতের যে কোনও ব্যবহারের জন্য ।

এটি লক্ষণীয় গুরুত্বপূর্ণ, এমনকি যদি আপনার টুকরোগুলির জন্য আপনার রেফারেন্সের প্রয়োজন নাও হয়, তবুও আপনার পদ্ধতিতে / instantiateItemঘিরে থাকা আপনার সমস্ত ট্যাবগুলির জন্য এইভাবে কল করা উচিত :startUpdatefinishUpdateonCreate

    adapter.startUpdate(viewPager);
    // ignoring return values of the below 2 calls, just side effects matter:
    adapter.instantiateItem(viewPager, 0);
    adapter.instantiateItem(viewPager, 1);
    adapter.finishUpdate(viewPager);

আপনি তা করেন না, তাহলে আপনি ঝুঁকি যে আপনার টুকরা দৃষ্টান্ত হবে না প্রতিশ্রুতিবদ্ধ করতে FragmentManagerযখন আপনার কার্যকলাপের ফোরগ্রাউন্ড হয়ে instantiateItemআপনার টুকরা প্রাপ্ত স্বয়ংক্রিয়ভাবে বলা হবে, কিন্তু startUpdate/ finishUpdate পারে কারনের জন্য, এটা ব্যর্থ এবং এইভাবে সৃষ্টি করবে এবং নতুন ব্যবহার করুন, যখন আপনার ওয়ারগুলি এখনও পুরানোগুলি উল্লেখ করবে। না (বাস্তবায়ন বিবরণ উপর নির্ভর করে) এবং তারা কি মূলত কর শুরু করা / প্রতিশ্রুতিবদ্ধ a FragmentTransaction
এই হতে পারে নির্মিত টুকরা দৃষ্টান্ত উল্লেখ করার ফল খুব দ্রুত হারিয়ে যাচ্ছে এবং প্রয়োজনীয় তুলনায় অনেক বেশি ঘন ঘন recreated (উদাহরণস্বরূপ, যখন আপনি আপনার পর্দায় ঘোরাতে)। আপনার টুকরো কতটা "ভারী" তার উপর নির্ভর করে এর অ-উপেক্ষিত কর্মক্ষমতা হতে পারে।
তদ্ব্যতীত, এই জাতীয় ক্ষেত্রে স্থানীয় ভার্সে টুকরো টুকরো টুকরো টুকরো থাকতে পারেবাসি হয়ে উঠুন: অ্যান্ড্রয়েড প্ল্যাটফর্ম যদি এগুলি নেওয়ার চেষ্টা করে তবেFragmentManager


4
এটি কিছু ক্ষেত্রে সেরা সমাধান হতে পারে। তবে ফ্র্যাগমেন্টম্যাঞ্জার যদি খণ্ডটি মেরে তা আবৃত্তি করে তবে কী হবে?
ওয়ালট্রান

4
@woltran FragmentManagerশুধু এলোমেলোভাবে না পারেন, হত্যা ( ধ্বংস সঠিক শব্দ এখানে) আপনার Fragment(মনে কি হবে যদি এটি একটি হত্যা করার সিদ্ধান্ত নিয়েছে Fragmentযে বর্তমানে প্রদর্শিত হচ্ছে;))। সাধারণত ক এর জীবনচক্র Fragmentতার আবদ্ধ থাকে Activity( বিশদ জন্য github.com/xxv/android-lifecycle দেখুন) -> Fragmentএটিকে ধ্বংস করা হলে কেবল এটিই Activityধ্বংস করা যায়। এমন ক্ষেত্রে যখন কোনও ব্যবহারকারী প্রদত্ত দিকে আবার নেভিগেট করে Activityতার onCreateআবার কল করা হবে এবং এর নতুন একটি উদাহরণ তৈরি করা Fragmentহবে।
মুরওয়ওয়াই

এটি সত্যই উত্তর
এমজে স্টুডিও

উদাহরণস্বরূপ, কোনও ব্যবহারকারী স্ক্রল ভিউপ্যাজার হিসাবে তৈরি হওয়ার উপর নির্ভর করার পরিবর্তে আপনার কি টুকরোগুলি তৈরি করা উচিত?
ইয়ার

@ ইয়ার হ্যাঁ, আপনার সত্যই হওয়া উচিত। আমি যে দস্তাবেজগুলি সরবরাহ করেছি সেটি স্পষ্টভাবে উল্লেখ করে এবং "কিছু অতিরিক্ত তথ্য" বিভাগটি কেন তা ব্যাখ্যা করে।
মোগওয়াই

13

আমি এটি যেভাবে করেছি তা হ'ল WeKReferences এর একটি হ্যাশটেবলের সংজ্ঞা দেওয়া হল:

protected Hashtable<Integer, WeakReference<Fragment>> fragmentReferences;

তারপরে আমি getItem () পদ্ধতিটি এভাবে লিখেছি:

@Override
public Fragment getItem(int position) {

    Fragment fragment;
    switch(position) {
    case 0:
        fragment = new MyFirstFragmentClass();
        break;

    default:
        fragment = new MyOtherFragmentClass();
        break;
    }

    fragmentReferences.put(position, new WeakReference<Fragment>(fragment));

    return fragment;
}

তারপরে আপনি একটি পদ্ধতি লিখতে পারেন:

public Fragment getFragment(int fragmentId) {
    WeakReference<Fragment> ref = fragmentReferences.get(fragmentId);
    return ref == null ? null : ref.get();
}

এটি ভালভাবে কাজ করছে বলে মনে হচ্ছে এবং আমি এটির চেয়ে একটু কম হ্যাকি পেয়েছি

"android:switcher:" + viewId + ":" + position

কৌশল, কারণ এটি কীভাবে ফ্র্যাগমেন্টপাগারএডাপ্টার প্রয়োগ করা হয় তার উপর নির্ভর করে না। অবশ্যই যদি খণ্ডটি ফ্র্যাগমেন্টপাগারএডাপ্টার দ্বারা প্রকাশ করা হয়েছে বা এটি এখনও তৈরি না করা হয়েছে, তবে getFragment বাতিল হয়ে যাবে।

এই পদ্ধতির সাথে যদি কারও কোনও ভুল মনে হয় তবে মন্তব্যগুলি স্বাগত অপেক্ষা বেশি।


int fragmentIdনাম পরিবর্তন করা উচিতint position
lmaooooo

7
আমি খুব অনুরূপ পন্থা ব্যবহার করছিলাম। পেজার যখন সেভস্টেট বান্ডেল থেকে তৈরি করা হয় তখন এটি ব্যর্থ হয়। উদাহরণস্বরূপ: ক্রিয়াকলাপ পটভূমিতে চলে যায় এবং onSavedStateInstance () বলা হওয়ার পরে অগ্রভাগে ফিরে আসে। সেক্ষেত্রে getItem () পদ্ধতিগুলি কল করা হবে না।
অনূপ

আপনার নিজের মানচিত্র তৈরির কারণটি যেহেতু ফ্র্যাগমেন্টম্যানেজারে ইতিমধ্যে সবসময় আপডেট থাকে? বিস্তারিত জানার জন্য আমার উত্তর দেখুন।
মর্গওয়াই

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

4
সিস্টেমটি খণ্ডগুলি পুনরায় তৈরি করার পরে এটি সঠিকভাবে কাজ করবে না।
এপিকপান্ডাফোরস

10

আমি এই পদ্ধতিটি তৈরি করেছি যা বর্তমান খণ্ডটির রেফারেন্স পেতে আমার পক্ষে কাজ করছে।

public static Fragment getCurrentFragment(ViewPager pager, FragmentPagerAdapter adapter) {
    try {
        Method m = adapter.getClass().getSuperclass().getDeclaredMethod("makeFragmentName", int.class, long.class);
        Field f = adapter.getClass().getSuperclass().getDeclaredField("mFragmentManager");
        f.setAccessible(true);
        FragmentManager fm = (FragmentManager) f.get(adapter);
        m.setAccessible(true);
        String tag = null;
        tag = (String) m.invoke(null, pager.getId(), (long) pager.getCurrentItem());
        return fm.findFragmentByTag(tag);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } 
    return null;
}

ভাল পারফরম্যান্সের জন্য পদ্ধতির বাইরে পদ্ধতি এবং ক্ষেত্রটি তৈরির কথা মনে করে খুব ভাল
মার্কোস

2

@ personne3000 দ্বারা প্রস্তাবিত সমাধানটি দুর্দান্ত, তবে এটির একটি সমস্যা রয়েছে: যখন কার্যকলাপ ব্যাকগ্রাউন্ডে যায় এবং সিস্টেমের দ্বারা নিহত হয় (কিছু নিখরচায় স্মৃতি পেতে) এবং তারপরে পুনরুদ্ধার fragmentReferencesকরা হয়, কারণ এটি খালি হবে, কারণgetItem হবে না বলা হয়।

নীচের শ্রেণিগুলি এ জাতীয় পরিস্থিতি পরিচালনা করে:

public abstract class AbstractHolderFragmentPagerAdapter<F extends Fragment> extends FragmentPagerAdapter {

    public static final String FRAGMENT_SAVE_PREFIX = "holder";
    private final FragmentManager fragmentManager; // we need to store fragment manager ourselves, because parent's field is private and has no getters.

    public AbstractHolderFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
        fragmentManager = fm;
    }

    private SparseArray<WeakReference<F>> holder = new SparseArray<WeakReference<F>>();

    protected void holdFragment(F fragment) {
        holdFragment(holder.size(), fragment);
    }

    protected void holdFragment(int position, F fragment) {
        if (fragment != null)
            holder.put(position, new WeakReference<F>(fragment));
    }

    public F getHoldedItem(int position) {
        WeakReference<F> ref = holder.get(position);
        return ref == null ? null : ref.get();
    }

    public int getHolderCount() {
        return holder.size();
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) { // code inspired by Google's FragmentStatePagerAdapter implementation
        super.restoreState(state, loader);
        Bundle bundle = (Bundle) state;
        for (String key : bundle.keySet()) {
            if (key.startsWith(FRAGMENT_SAVE_PREFIX)) {
                int index = Integer.parseInt(key.substring(FRAGMENT_SAVE_PREFIX.length()));
                Fragment f = fragmentManager.getFragment(bundle, key);
                holdFragment(index, (F) f);
            }
        }
    }

    @Override
    public Parcelable saveState() {
        Bundle state = (Bundle) super.saveState();
        if (state == null)
            state = new Bundle();

        for (int i = 0; i < holder.size(); i++) {
            int id = holder.keyAt(i);
            final F f = getHoldedItem(i);
            String key = FRAGMENT_SAVE_PREFIX + id;
            fragmentManager.putFragment(state, key, f);
        }
        return state;
    }
}

2

খণ্ডগুলিতে হ্যান্ডেল পাওয়ার প্রধান প্রধান ব্লকটি হ'ল আপনি getItem () এ নির্ভর করতে পারবেন না। ওরিয়েন্টেশন পরিবর্তনের পরে, খণ্ডগুলির উল্লেখগুলি বাতিল হয়ে যাবে এবং getItem () আবার কল করা হবে না।

ট্যাগ পাওয়ার জন্য ফ্রেগমেন্টপেজারএডাপ্টার প্রয়োগের উপর নির্ভর করে না এমন একটি পদ্ধতির এটি এখানে। ইনস্ট্যান্টিয়েট আইটেম () ওভাররাইড করুন যা getItem () থেকে তৈরি খণ্ডটি ফেরত দেবে বা খণ্ড পরিচালক থেকে পাওয়া যাবে।

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object value =  super.instantiateItem(container, position);

    if (position == 0) {
        someFragment = (SomeFragment) value;
    } else if (position == 1) {
        anotherFragment = (AnotherFragment) value;
    }

    return value;
}

0

ফ্র্যাগমেন্টপেজারএডাপ্টার থেকে টুকরো ফিরতে এই পোস্টটি দেখুন । আপনার খণ্ডটির সূচি জেনে আপনার উপর নির্ভর করে - তবে এটি getItem () এ সেট করা হবে (কেবলমাত্র তাত্ক্ষণিক সময়ে)


0

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

@Override
public void onAttach(Context context){
    super.onAttach(context);
    MainActivity.fragId = getId();
}

এবং তারপরে আপনি কেবল ক্রিয়াকলাপের ভিতরে সহজেই খণ্ডটি অ্যাক্সেস করতে পারেন:

Fragment f = getSupportFragmentManager.findFragmentById(fragId);

0

আমি জানি না এটি সর্বোত্তম পন্থা কিনা তবে আমার পক্ষে আর কিছুই কাজ করেনি। গেটএ্যাকটিভফ্র্যাগমেন্ট সহ অন্যান্য সমস্ত বিকল্প বাতিল হয়ে গেছে বা অ্যাপটিকে ক্র্যাশ করেছে।

আমি লক্ষ্য করেছি যে স্ক্রিন রোটেশনে খণ্ডটি সংযুক্ত ছিল তাই আমি খণ্ডটি ক্রিয়াকলাপে ফিরে পাঠাতে ব্যবহার করেছি।

খণ্ডে:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnListInteractionListener) activity;
        mListener.setListFrag(this);
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

তারপরে ক্রিয়াকলাপে:

@Override
public void setListFrag(MyListFragment lf) {
    if (mListFragment == null) {
        mListFragment = lf;
    }
}

এবং অবশেষে ক্রিয়্যাট অন্বেষণে ():

if (savedInstanceState != null) {
    if (mListFragment != null)
        mListFragment.setListItems(items);
}

এই পদ্ধতির কোনও নতুন তৈরি না করে ক্রিয়াকলাপে প্রকৃত দৃশ্যমান খণ্ডকে সংযুক্ত করে।


0

আমি জাভা / অ্যান্ড্রয়েডের সাথে সম্পর্কিত যেহেতু আমার পদ্ধতিটি সঠিক বা সর্বোত্তম উপায় ছিল কিনা তা নিশ্চিত নয় তবে এটি কাজ করেছিল (আমি নিশ্চিত যে এটি অবজেক্ট ওরিয়েন্টেড নীতিগুলি লঙ্ঘন করেছে তবে আমার ব্যবহারের ক্ষেত্রে অন্য কোনও সমাধান কার্যকর হয়নি)।

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

public interface Callbacks {
    public void addFragment (Fragment fragment);
    public void removeFragment (Fragment fragment);
}

হোস্টিং ক্রিয়াকলাপে আমি ইন্টারফেসটি প্রয়োগ করেছি এবং টুকরো টুকরো রাখার জন্য একটি লিঙ্কডহ্যাসসেট তৈরি করেছি:

public class HostingActivity extends AppCompatActivity implements ViewPagerFragment.Callbacks {

    private LinkedHashSet<Fragment> mFragments = new LinkedHashSet<>();

    @Override
    public void addFragment (Fragment fragment) {
        mFragments.add(fragment);
    }

    @Override
    public void removeFragment (Fragment fragment) {
        mFragments.remove(fragment);
    }
}

ভিউপাগারফ্রেগমেন্ট ক্লাসের মধ্যে আমি টেক্সটগুলিকে অনাটাচের মধ্যে তালিকায় যুক্ত করে ওনডাটাচের মধ্যে এগুলি সরিয়েছি:

public class ViewPagerFragment extends Fragment {

    private Callbacks mCallbacks;

    public interface Callbacks {
        public void addFragment (Fragment fragment);
        public void removeFragment (Fragment fragment);
    } 

    @Override
    public void onAttach (Context context) {
        super.onAttach(context);
        mCallbacks = (Callbacks) context;
        // Add this fragment to the HashSet in the hosting activity
        mCallbacks.addFragment(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Remove this fragment from the HashSet in the hosting activity
        mCallbacks.removeFragment(this);
        mCallbacks = null;
    }
}

হোস্টিং ক্রিয়াকলাপের মধ্যে আপনি এখন ফ্র্যাগমেন্টস্টেটপেজারএডাপ্টারে বিদ্যমান টুকরোগুলি পুনরুক্ত করার জন্য এমফ্রেগমেন্টগুলি ব্যবহার করতে সক্ষম হবেন।


0

এই শ্রেণিটি অভ্যন্তরীণ ট্যাগগুলির উপর নির্ভর না করে কৌশলটি করে। সতর্কতা: টুকরাগুলিকে getFrament পদ্ধতি ব্যবহার করে অ্যাক্সেস করা উচিত এবং getItem এক নয়।

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final Map<Integer, Reference<Fragment>> fragments = new HashMap<>();
    private final List<Callable0<Fragment>> initializers = new ArrayList<>();
    private final List<String> titles = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    void addFragment(Callable0<Fragment> initializer, String title) {
        initializers.add(initializer);
        titles.add(title);
    }

    public Optional<Fragment> getFragment(int position) {
        return Optional.ofNullable(fragments.get(position).get());
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment =  initializers.get(position).execute();
        return fragment;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        fragments.put(position, new WeakReference<>(fragment));
        return fragment;
    }

    @Override
    public int getCount() {
        return initializers.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }
}

-5

এই কোডটি চেষ্টা করে দেখুন,

public class MYFragmentPAdp extends FragmentPagerAdapter {

    public MYFragmentPAdp(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 2;
    }

     @Override
     public Fragment getItem(int position) {
         if (position == 0)
             Fragment fragment = new Fragment1();
         else (position == 1)
             Fragment fragment = new Fragment2();
         return fragment;
     }
}

নজিব, যেমন আমি নীচে আমার উত্তরে গেট আইটেমটি ব্যাখ্যা করেছি () বিদ্যমান নামগুলি প্রত্যাবর্তনের পরিবর্তে নতুন খণ্ড তৈরি করছে কারণ যে কোনও ব্যক্তি প্রদত্ত নাম পাবে এবং না তৈরির প্রত্যাশা করতে পারে । আমার পোস্টটি একই পোস্টে দেখুন।
ইসমার স্লোমিক

খণ্ড খণ্ড = নতুন আপনার কাস্টমফ্রেগমেন্টক্লাস (); এখানে এটি পরীক্ষা করে দেখুন।
নাজিব আহমেদ পুঠোওয়ালা

আমি এখনও বুঝতে পারি না যে এটি বিদ্যমান
অবস্থার

আপনি এখনও আপনার কাস্টম টুকরাটির জন্য প্রারম্ভিকভাবে ফিরে যান, যেমন ফ্রেগমেন্ট টুকরা = নতুন আপনার ফ্রেগমেন্ট (); রিটার্ন টুকরা;
নাজিব আহমেদ পুঠোওয়ালা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.