ส่งข้อมูลจากกิจกรรมไปยังส่วนใน Android


316

ฉันมีสองชั้น EditTextแรกคือกิจกรรมที่สองคือส่วนที่ฉันมีบางอย่าง ในกิจกรรมฉันมีคลาสย่อยที่มี async-task และในวิธีที่doInBackgroundฉันได้รับผลบางอย่างซึ่งฉันบันทึกลงในตัวแปร ฉันจะส่งตัวแปรนี้จากคลาสย่อย "กิจกรรมของฉัน" ไปยังส่วนนี้ได้อย่างไร

คำตอบ:


662

จากกิจกรรมที่คุณส่งข้อมูลโดยมีเจตนาดังนี้:

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

และในส่วนวิธีการ onCreateView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    String strtext = getArguments().getString("edttext");    
    return inflater.inflate(R.layout.fragment, container, false);
}

15
คุณสามารถส่งวัตถุไปยังชิ้นส่วนได้หรือไม่
yeahman

63
ฉันได้รับ NullPointerException เมื่อโทรแล้วgetArguments().getString(key)
Nima G

9
NullPointerException "สตริง strtext setArguments (). getString (" edttext ");"
Jorgesys

4
ในขณะที่อ่านเนื้อหาของชุดข้อมูลเป็นส่วนแรกมักจะได้รับชุดข้อมูลเป็นวัตถุชุดรวมโดยใช้วิธีการ getArguments และตรวจสอบกับค่าว่าง มิฉะนั้นจะใช้เมธอด getString เป็นโมฆะดังนั้น NPE จะไม่มีการส่งบันเดิล สิ่งนี้จะหลีกเลี่ยงข้อยกเว้นตัวชี้โมฆะเมื่อไม่ได้ส่งบันเดิล
balachandarkm

3
@Aznix ไม่แนะนำให้สร้าง constructor สำหรับแฟรกเมนต์
Azam

108

นอกจากนี้คุณสามารถเข้าถึงข้อมูลกิจกรรมได้จากส่วน:

กิจกรรม:

public class MyActivity extends Activity {

    private String myString = "hello";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        ...
    }

    public String getMyData() {
        return myString;
    }
}

Fragment:

public class MyFragment extends Fragment {

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

        MyActivity activity = (MyActivity) getActivity();
        String myDataFromActivity = activity.getMyData();
        return view;
    }
}

78
วิธีการแก้ปัญหานี้รวมการมีเพศสัมพันธ์อย่างแน่นหนาระหว่างกิจกรรมและชิ้นส่วนของคุณดีกว่าที่จะใช้Bundleชั้นเรียนเพื่อส่งผ่านข้อมูล หรือคุณสามารถทำให้getMyData()วิธีการสืบทอดและดำเนินการจากอินเตอร์เฟซและมีFragmentการตรวจสอบว่า getActivity กลับอินเตอร์เฟซในinstanceof onAttach()
ฤดี Kershaw

1
ทางออกนี้ดีที่สุดสำหรับฉัน นอกจากนี้ถ้า myString เป็นสาธารณะคุณยังไม่ได้ประกาศวิธี getMyData ()
Burak Öztürk

1
คำตอบที่ยอมรับในปัจจุบันส่งคืนข้อยกเว้นตัวชี้ null นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Richmond

9
นี่ไม่ควรเป็นคำตอบที่ยอมรับได้ คลัปแน่นสามารถหลีกเลี่ยงได้ง่าย โดยทั่วไปเป็นความคิดที่ไม่ดีและทำให้ชิ้นส่วนไร้ประโยชน์เช่นกันอาจไม่มีชิ้นส่วนถ้าคุณจะใช้มันเชื่อมโยงกับกิจกรรม ไม่สามารถนำแฟรกเมนต์มาใช้ในกิจกรรมอื่นได้
Martin Marconcini

51

ฉันพบคำตอบมากมายที่นี่ @ stackoverflow.com แต่แน่นอนว่านี่คือคำตอบที่ถูกต้องของ:

"กำลังส่งข้อมูลจากกิจกรรมไปยังแฟรกเมนต์ใน Android".

กิจกรรม:

        Bundle bundle = new Bundle();
        String myMessage = "Stackoverflow is cool!";
        bundle.putString("message", myMessage );
        FragmentClass fragInfo = new FragmentClass();
        fragInfo.setArguments(bundle);
        transaction.replace(R.id.fragment_single, fragInfo);
        transaction.commit();

Fragment:

อ่านค่าในส่วน

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = this.getArguments();
        String myValue = bundle.getString("message");
        ...
        ...
        ...
        }

หรือเพียงแค่

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        String myValue = this.getArguments().getString("message");
        ...
        ...
        ...
        }

ฉันเดาว่าไม่ใช่วิธีที่ดีที่สุดในการอัปเดต onQueryTextSubmit-search-results ใน ListView ซึ่งซ้อนอยู่ใน Fragment (ถ้ามีคนพิมพ์เร็วเขาจะส่ง args สองครั้งต่อวินาที) หรือไม่
Martin Pfeffer

1
สิ่งที่เกี่ยวกับ Object ติดตั้งของสตริงหรือ int?
Dario

2
@Jorgesys เกี่ยวกับวิธีแก้ปัญหานี้ developer.android.com/training/basics/fragments/…
yozhik

23

คำตอบนี้อาจจะสายเกินไป แต่จะเป็นประโยชน์สำหรับผู้อ่านในอนาคต

ฉันมีเกณฑ์บางอย่าง ฉันได้รหัสเพื่อเลือกไฟล์จากความตั้งใจ และไฟล์ที่เลือกที่จะส่งผ่านไปยังส่วนย่อยสำหรับกระบวนการต่อไป ฉันมีแฟรกเมนต์จำนวนมากที่มีฟังก์ชั่นการเลือกไฟล์ ในเวลานั้นทุกครั้งที่ตรวจสอบสภาพและรับเศษและส่งผ่านค่านั้นค่อนข้างน่าขยะแขยง ฉันเลยตัดสินใจส่งค่าโดยใช้อินเตอร์เฟส

ขั้นตอนที่ 1:สร้างส่วนต่อประสานบนกิจกรรมหลัก

   public interface SelectedBundle {
    void onBundleSelect(Bundle bundle);
   }

ขั้นตอนที่ 2:สร้างการอ้างอิง SelectedBundle ในกิจกรรมเดียวกัน

   SelectedBundle selectedBundle;

ขั้นตอนที่ 3:สร้างวิธีการในกิจกรรมเดียวกัน

   public void setOnBundleSelected(SelectedBundle selectedBundle) {
       this.selectedBundle = selectedBundle;
   }

ขั้นตอนที่ 4:ต้องเริ่มต้นการอ้างอิง SelectedBundle ซึ่งเป็นแฟรกเมนต์ทั้งหมดต้องการฟังก์ชั่น filepicker คุณวางรหัสนี้ในonCreateView(..)วิธีการแยกส่วนของคุณ

    ((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
          @Override
         public void onBundleSelect(Bundle bundle) {
            updateList(bundle);
        }
     });

ขั้นตอนที่ 5:กรณีของฉันฉันต้องส่งภาพ Uri จาก HomeActivity ไปยังส่วน ดังนั้นฉันใช้ฟังก์ชั่นนี้กับวิธี onActivityResult

onActivityResult จาก MainActivity ส่งค่าไปยังแฟรกเมนต์โดยใช้อินเตอร์เฟส

หมายเหตุ: กรณีของคุณอาจแตกต่างกัน คุณสามารถโทรหาจากที่ใดก็ได้จาก HomeActivity

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent  data) {
       selectedBundle.onBundleSelect(bundle);
  }

นั่นคือทั้งหมด ใช้ทุกส่วนที่คุณต้องการใน FragmentClass คุณทำได้ดีมาก. คุณทำไปแล้ว ว้าว...


15

แนวคิดพื้นฐานของการใช้แฟรกเมนต์ (F) คือการสร้างส่วนประกอบ UI ที่สามารถนำกลับมาใช้ใหม่ได้เองในแอปพลิเคชัน Android แฟรกเมนต์เหล่านี้มีอยู่ในกิจกรรมและมีวิธีการทั่วไปในการสร้างเส้นทางการสื่อสารจาก A -> F และ FA มันเป็นสิ่งที่ต้องสื่อสารระหว่าง FF ผ่านกิจกรรมเพราะมีเพียงเศษเล็กเศษน้อยและการค้ำจุนตนเอง

ดังนั้นการส่งผ่านข้อมูลจาก A -> F จะเหมือนกับที่อธิบายโดยρяσѕρєя K. นอกจากคำตอบนั้นหลังจากสร้างชิ้นส่วนภายในกิจกรรมแล้วเรายังสามารถส่งข้อมูลไปยังวิธีการเรียกใช้แฟรกเมนต์ในแฟรกเมนต์

ตัวอย่างเช่น:

    ArticleFragment articleFrag = (ArticleFragment)
                    getSupportFragmentManager().findFragmentById(R.id.article_fragment);
    articleFrag.updateArticleView(position);


15

วิธีที่ดีที่สุดและสะดวกสบายคือการเรียกใช้อินสแตนซ์แฟรกเมนต์และส่งข้อมูลในเวลานั้น ทุกส่วนโดยค่าเริ่มต้นมีวิธีการอินสแตนซ์

ตัวอย่างเช่น: ถ้าชื่อแฟรกเมนต์ของคุณคือMyFragment

ดังนั้นคุณจะเรียกชิ้นส่วนของคุณจากกิจกรรมเช่นนี้:

getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();

* R.id.container เป็นรหัสของ FrameLayout ของฉัน

ดังนั้นในMyFragment.newInstance ("data1", "data2")คุณสามารถส่งข้อมูลไปยังแฟรกเมนต์และในแฟรกเมนต์ของคุณคุณได้รับข้อมูลนี้ในMyFragment newInstance (String param1, String param2)

public static MyFragment newInstance(String param1, String param2) {
        MyFragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

จากนั้นในวิธีสร้างชิ้นส่วนonCreateคุณจะได้รับข้อมูล:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

ดังนั้นตอนนี้mParam1 มี data1และmParam2 มี data2

ตอนนี้คุณสามารถใช้mParam1และmParam2 ในส่วนของคุณ


R.id.container คืออะไรที่นี่ คุณหมายถึง R.id.container_current หรือไม่นี่คือค่า int
shaurya uppal

@s * R.id.container เป็น id ของ FrameLayout ของฉัน
Pre_hacker

จนถึงตอนนี้คำอธิบายที่ดีที่สุดที่ฉันเคยพบในการส่งผ่านข้อมูลเกี่ยวกับการเพิ่ม / แทนที่ส่วนโดยใช้ Fragment Manager ทำงานเหมือนอัญมณี! ขอบคุณ!
sam

ใช้ R.id.nav_host_fragment แทน R.id.container
Bahaa Hany

10

ฉันต้องการเพิ่มสำหรับผู้เริ่มต้นว่าความแตกต่างระหว่าง 2 คำตอบ upvoted ที่สุดที่นี่ได้รับจากการใช้ส่วนที่แตกต่างกัน

หากคุณใช้แฟรกเมนต์ภายในคลาส Java ที่คุณมีข้อมูลที่คุณต้องการส่งคุณสามารถใช้คำตอบแรกในการส่งผ่านข้อมูล:

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

หากคุณใช้ตัวอย่างเช่นรหัสเริ่มต้นที่ Android Studio ให้มากับชิ้นส่วนแบบแท็บรหัสนี้จะไม่ทำงาน

มันจะไม่ทำงานแม้ว่าคุณจะแทนที่ PlaceholderFragment ที่เป็นค่าเริ่มต้นด้วย FragmentClasses ของคุณและแม้ว่าคุณจะแก้ไข FragmentPagerAdapter ให้เป็นสถานการณ์ใหม่โดยเพิ่มสวิตช์สำหรับ getItem () และสวิตช์อื่นสำหรับ getPageTitle () ดังที่แสดงไว้ที่นี่ )

คำเตือน: คลิปดังกล่าวข้างต้นมีข้อผิดพลาดของรหัสซึ่งฉันจะอธิบายในภายหลังที่นี่ แต่มีประโยชน์เพื่อดูว่าคุณไปจากรหัสเริ่มต้นไปยังรหัสที่แก้ไขได้สำหรับชิ้นส่วนแท็บ)! ส่วนที่เหลือของคำตอบของฉันเหมาะสมกว่าถ้าคุณพิจารณาคลาส java และไฟล์ xml จากคลิปนั้น (แทนการใช้แฟรกเมนต์แบบแท็บเป็นครั้งแรกโดยสถานการณ์เริ่มต้น)

เหตุผลหลักที่คำตอบที่ได้รับการโหวตมากที่สุดจากหน้านี้จะไม่ทำงานคือในรหัสเริ่มต้นสำหรับแฟรกเมนต์แบบแท็บแฟรกเมนต์ถูกใช้ในคลาส Java อื่น: FragmentPagerAdapter!

ดังนั้นเพื่อที่จะส่งข้อมูลคุณถูกล่อลวงให้สร้างมัดใน MotherActivity และส่งผ่านมันใน FragmentPagerAdapter โดยใช้คำตอบที่ 2

เฉพาะที่ผิดอีกครั้ง ( อาจเป็นไปได้ที่คุณจะทำเช่นนั้น แต่มันก็เป็นแค่ความยุ่งยากที่ไม่จำเป็นจริงๆ )

ฉันคิดว่าวิธีที่ถูกต้อง / ทำได้ง่ายกว่าคือการส่งข้อมูลโดยตรงไปยังส่วนที่เป็นปัญหาโดยใช้คำตอบหมายเลข 2 ใช่จะมีการแต่งงานกันอย่างแน่นหนาระหว่างกิจกรรมและ Fragment, BUT แต่สำหรับชิ้นส่วนแบบแท็บนั่นเป็นสิ่งที่คาดหวัง ฉันอยากจะแนะนำให้คุณสร้างชิ้นส่วนแบบแท็บภายในคลาส JavaActivity (เป็น subclasses เนื่องจากมันจะไม่ถูกใช้นอก MotherActivity) - มันง่ายเพียงเพิ่มในคลาส JavaActivity เป็นชิ้นส่วนจำนวนมากตามที่คุณต้องการ:

 public static class Tab1 extends Fragment {

    public Tab1() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
        return rootView;
    }
}.

ดังนั้นในการส่งข้อมูลจาก MotherActivity ไปยัง Fragment คุณจะต้องสร้าง Strings / Bundles ส่วนตัวเหนือ onCreate ของกิจกรรม Mother - ซึ่งคุณสามารถกรอกข้อมูลที่คุณต้องการส่งไปยังแฟรกเมนต์และส่งผ่านทาง วิธีการสร้างขึ้นหลังจาก onCreate (ที่นี่เรียกว่า getMyData ())

public class MotherActivity extends Activity {

    private String out;
    private Bundle results;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mother_activity);

       // for example get a value from the previous activity
        Intent intent = getIntent();
        out = intent.getExtras().getString("Key");

    }

    public Bundle getMyData() {
        Bundle hm = new Bundle();
        hm.putString("val1",out);
        return hm;
    }
}

และจากนั้นในคลาสแฟรกเมนต์คุณใช้ getMyData:

public static class Tab1 extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public Tab1() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
            TextView output = (TextView)rootView.findViewById(R.id.your_id_for_a_text_view_within_the_layout);

            MotherActivity activity = (MotherActivity)getActivity();

            Bundle results = activity.getMyData();
            String value1 = results.getString("val1");

            output.setText(value1);
            return rootView;
        }
    }

หากคุณมีการสืบค้นฐานข้อมูลฉันแนะนำให้คุณทำใน MotherActivity (และส่งผลลัพธ์เป็น Strings / Integers ที่แนบกับคีย์ในชุดข้อมูลดังที่แสดงด้านบน) เนื่องจากภายในแฟรกเมนต์แบบแท็บไวยากรณ์ของคุณจะซับซ้อนมากขึ้น () ตัวอย่างเช่นและ getIntent จะกลายเป็น getActivity (). getIntent) แต่คุณก็มีตัวเลือกให้ทำตามที่คุณต้องการ

คำแนะนำของฉันสำหรับผู้เริ่มต้นคือการมุ่งเน้นไปที่ขั้นตอนเล็ก ๆ ก่อนอื่นจงตั้งใจให้เปิดกิจกรรมแท็บที่ง่ายมากโดยไม่ต้องผ่านข้อมูลใด ๆ ใช้งานได้หรือไม่ มันเปิดแท็บที่คุณคาดหวังหรือไม่ ถ้าไม่ทำไม

เริ่มต้นจากนั้นและโดยการใช้วิธีแก้ไขปัญหาเช่นที่นำเสนอในคลิปนี้ดูว่ามีอะไรขาดหายไป สำหรับคลิปนั้น ๆ mainactivity.xml จะไม่ปรากฏขึ้น นั่นจะทำให้คุณสับสนอย่างแน่นอน แต่ถ้าคุณให้ความสนใจคุณจะเห็นว่าตัวอย่างเช่นบริบท (เครื่องมือ: บริบท) นั้นผิดในไฟล์ส่วน xml แต่ละ XML ของแฟรกเมนต์ต้องชี้ไปที่คลาสแฟรกเมนต์ที่ถูกต้อง (หรือคลาสย่อยโดยใช้ตัวคั่น $)

คุณจะเห็นว่าในคลาสกิจกรรมหลักของจาวาคุณต้องเพิ่ม tabLayout.setupWithViewPager (mViewPager) - หลังจากบรรทัด TabLayout tabLayout = (TabLayout) findViewById (R.id.tabs); หากไม่มีบรรทัดนี้มุมมองของคุณจะไม่เชื่อมโยงกับไฟล์ XML ของแฟรกเมนต์ แต่จะแสดงเฉพาะไฟล์ xml ของกิจกรรมหลักเท่านั้น

นอกจากบรรทัดในคลาส java กิจกรรมหลักในไฟล์ XML ของกิจกรรมหลักคุณต้องเปลี่ยนแท็บให้เหมาะกับสถานการณ์ของคุณ (เช่นเพิ่มหรือลบ TabItems) หากคุณไม่มีแท็บใน XML กิจกรรมหลักอาจเป็นไปได้ว่าคุณไม่ได้เลือกประเภทกิจกรรมที่ถูกต้องเมื่อคุณสร้างขึ้นในสถานที่แรก (กิจกรรมใหม่ - กิจกรรมแบบแท็บ)

โปรดทราบว่าใน 3 ย่อหน้าสุดท้ายฉันพูดถึงวิดีโอ! ดังนั้นเมื่อฉันพูด XML กิจกรรมหลักมันเป็น XML กิจกรรมหลักในวิดีโอซึ่งในสถานการณ์ของคุณคือไฟล์ MotherActivity XML


8

หากคุณส่งการอ้างอิงไปยังแฟรกเมนต์ (คลาสย่อยคอนกรีตของ) ลงในภารกิจ async คุณสามารถเข้าถึงแฟรกเมนต์ได้โดยตรง

วิธีการบางส่วนในการส่งการอ้างอิงส่วนย่อยไปยังงาน async:

  • ถ้างาน async ของคุณเป็นคลาสที่เต็มเปี่ยม ( class FooTask extends AsyncTask) ให้ส่งแฟรกเมนต์ของคุณไปยังตัวสร้าง
  • หากงาน async ของคุณเป็นคลาสภายในให้ประกาศตัวแปร Fragment สุดท้ายในขอบเขตที่กำหนดภารกิจ async หรือเป็นฟิลด์ของคลาสภายนอก คุณจะสามารถเข้าถึงได้จากชั้นใน

คำตอบของคุณดูเหมือนจะเป็นสิ่งที่ถูกต้องสำหรับฉันคุณสามารถขยายเพิ่มอีกนิดด้วยการใส่โค้ดตัวอย่างให้ทำหรือไม่?
Leon Armstrong

6

บางครั้งคุณสามารถรับเจตนาในกิจกรรมของคุณและคุณต้องส่งข้อมูลไปยังส่วนที่ทำงานของคุณ
คำตอบที่ได้รับก็โอเคถ้าคุณต้องการเริ่มแฟรกเมนต์ แต่ถ้ามันยังทำงานsetArguments()อยู่มันก็ไม่มีประโยชน์อะไร
ปัญหาอื่นเกิดขึ้นถ้าข้อมูลที่ส่งผ่านจะทำให้เกิดการโต้ตอบกับ UI ของคุณ ในกรณีนี้คุณไม่สามารถโทรหาสิ่งที่ต้องการได้myfragment.passData()เพราะ android จะบอกได้อย่างรวดเร็วว่าเฉพาะเธรดที่สร้างมุมมองเท่านั้นที่สามารถโต้ตอบได้

ดังนั้นข้อเสนอของฉันคือการใช้ผู้รับ ด้วยวิธีนี้คุณสามารถส่งข้อมูลได้จากทุกที่รวมถึงกิจกรรม แต่งานจะเสร็จภายในบริบทของแฟรกเมนต์

ในส่วนของคุณonCreate():

protected DataReceiver dataReceiver;
public static final String REC_DATA = "REC_DATA";

@Override
public void onCreate(Bundle savedInstanceState) {


    data Receiver = new DataReceiver();
    intentFilter = new IntentFilter(REC_DATA);

    getActivity().registerReceiver(dataReceiver, intentFilter);
}

private class DataReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        int data= intent.getIntExtra("data", -1);

        // Do anything including interact with your UI
    }
}

ในกิจกรรมของคุณ:

// somewhere
Intent retIntent = new Intent(RE_DATA);
retIntent.putExtra("data", myData);
sendBroadcast(retIntent);

5

โพสต์เก่ามากฉันยังคงกล้าที่จะเพิ่มคำอธิบายเล็ก ๆ น้อย ๆ ที่จะเป็นประโยชน์สำหรับฉัน

ในทางเทคนิคคุณสามารถตั้งค่าสมาชิกประเภทใดก็ได้ในส่วนจากกิจกรรมโดยตรง
ดังนั้นทำไม Bundle
เหตุผลง่ายมาก - Bundle มีวิธีที่เหมือนกันในการจัดการ:
- การสร้าง / เปิด
แฟรกเมนต์ - การกำหนดค่าใหม่ (การหมุนหน้าจอ) - เพียงเพิ่มบันเดิลเริ่มต้น / อัปเดตเพื่อ outState ใน onSaveInstanceState ()
- การคืนค่าแอป เช่นเดียวกับการกำหนดค่าใหม่)

คุณสามารถ (ถ้าคุณชอบการทดลอง) สร้างวิธีแก้ปัญหาในสถานการณ์ที่เรียบง่าย แต่วิธีการ Bundle ก็ไม่เห็นความแตกต่างระหว่างหนึ่งส่วนและหนึ่งพันบนแบ็คสแต็ค - มันยังคงง่ายและตรงไปตรงมา
นั่นเป็นเหตุผลที่คำตอบของ@Elenasysเป็นคำตอบที่สง่างามและเป็นสากลที่สุด
และนั่นเป็นเหตุผลที่คำตอบของ@Martinมีข้อผิดพลาด


4

วิธีที่ดีกว่าสำหรับการส่งข้อมูลจากคลาสกิจกรรมไปยังแฟรกเมนต์คือการส่งผ่านวิธี setter ชอบ

FragmentClass fragmentClass = new FragmentClass();
fragmentClass.setMyList(mylist);
fragmentClass.setMyString(myString);
fragmentClass.setMyMap(myMap);

และรับข้อมูลเหล่านี้จากชั้นเรียนได้อย่างง่ายดาย


วิธีการส่งผ่านข้อมูลจากส่วนไปยังส่วนเช่นstackoverflow.com/questions/32953477/pass-data-to-fragment
Hoo

สิ่งนี้ไม่สะดวกมากเมื่อคุณผ่านไปด้วยเช่นกันซึ่งก่อนหน้านี้ตั้งค่าไว้เป็นพิเศษ
เจอราร์ด

หากคุณต้องการให้ข้อมูลถูกตั้งค่าเป็นบางฟิลด์ในแฟรกเมนต์ของคุณและยังไม่สามารถมองเห็นได้ (เริ่มต้น) คุณจะได้รับ NPE
yozhik


ฉันหยุดทำงานกับ Android เมื่อ 3 ปีที่แล้วสิ่งเหล่านี้อาจเลิกใช้แล้ว
ssi-anik

4

จากActivityคุณส่งข้อมูลด้วย Bundle เป็น:

Bundle bundle = new Bundle();
bundle.putString("data", "Data you want to send");

// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);

และในFragmentวิธี onCreateView รับข้อมูล:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
    String data = getArguments().getString("data");// data which sent from activity  
    return inflater.inflate(R.layout.myfragment, container, false);
}

3

หากactivityความต้องการที่จะทำให้การfragmentดำเนินการหลังจากการเริ่มต้นวิธีที่ง่ายที่สุดคือการactivityมีวิธีการเรียกใช้ในfragmentอินสแตนซ์ ในการfragmentเพิ่มวิธีการ:

public class DemoFragment extends Fragment {
  public void doSomething(String param) {
      // do something in fragment
  }
}

จากนั้นในการactivityเข้าถึงการfragmentใช้งานของfragmentผู้จัดการและโทรไปที่method:

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DemoFragment fragmentDemo = (DemoFragment) 
            getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
        fragmentDemo.doSomething("some param");
    }
}

แล้วactivityสามารถสื่อสารโดยตรงกับอัญเชิญนี้fragmentmethod


1
นี่เป็นสิ่งที่ดีจริงๆในแง่ที่ว่าคุณไม่ต้องการที่จะเข้าสู่onCreateViewวิธีการในส่วน มีประโยชน์จริง ๆ
Young Emil

2

ใช้อินเตอร์เฟสต่อไปนี้เพื่อสื่อสารระหว่างกิจกรรมและแฟรกเมนต์

public interface BundleListener {
    void update(Bundle bundle);
    Bundle getBundle();
}

หรือใช้ตามผู้ฟังทั่วไปนี้เพื่อการสื่อสารสองทางโดยใช้อินเตอร์เฟส

 /**
 * Created by Qamar4P on 10/11/2017.
 */
public interface GenericConnector<T,E> {
    T getData();
    void updateData(E data);
    void connect(GenericConnector<T,E> connector);
}

วิธีการแสดงส่วน

public static void show(AppCompatActivity activity) {
        CustomValueDialogFragment dialog = new CustomValueDialogFragment();
        dialog.connector = (GenericConnector) activity;
        dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
    }

คุณสามารถโยนบริบทของคุณไปGenericConnectorในonAttach(Context)เกินไป

ในกิจกรรมของคุณ

CustomValueDialogFragment.show(this);

ในส่วนของคุณ

...
@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        connector.connect(new GenericConnector() {
            @Override
            public Object getData() {
                return null;
            }

            @Override
            public void updateData(Object data) {

            }

            @Override
            public void connect(GenericConnector connector) {

            }
        });
    }
...
    public static void show(AppCompatActivity activity, GenericConnector connector) {
            CustomValueDialogFragment dialog = new CustomValueDialogFragment();
            dialog.connector = connector;
            dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
        }

หมายเหตุ: ไม่เคยใช้มันเหมือน"".toString().toString().toString();วิธี


2

เพิ่งสะดุดกับคำถามนี้ในขณะที่วิธีการส่วนใหญ่จะทำงานได้ ฉันแค่ต้องการเพิ่มว่าคุณสามารถใช้Event Bus Libraryโดยเฉพาะอย่างยิ่งในสถานการณ์ที่ไม่ได้สร้างส่วนประกอบ (Activity หรือ Fragment) มันดีสำหรับโครงการ Android ทุกขนาดและกรณีการใช้งานมากมาย ฉันใช้มันเป็นการส่วนตัวในหลายโครงการที่ฉันมีใน playstore


1

คุณสามารถสร้างวิธีการคงที่สาธารณะในส่วนที่คุณจะได้รับการอ้างอิงแบบคงที่ของชิ้นส่วนนั้นและส่งผ่านข้อมูลไปยังฟังก์ชั่นนั้นและตั้งค่าข้อมูลที่จะโต้แย้งในวิธีเดียวกันและรับข้อมูลผ่าน getArgument บนวิธีการสร้างชิ้นส่วน ตัวแปร


1

วิธีทดสอบและส่งข้อมูลระหว่างแฟรกเมนต์และกิจกรรมที่ฉลาดที่สุดคือการสร้างตัวแปรตัวอย่าง:

class StorageUtil {
  public static ArrayList<Employee> employees;
}

จากนั้นเมื่อต้องการส่งผ่านข้อมูลจากแฟรกเมนต์ไปยังกิจกรรมเราดำเนินการดังกล่าวในวิธีการของ

//a field created in the sending fragment
ArrayList<Employee> employees;

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
         employees=new ArrayList();

       //java 7 and above syntax for arraylist else use employees=new ArrayList<Employee>() for java 6 and below

     //Adding first employee
        Employee employee=new Employee("1","Andrew","Sam","1984-04-10","Male","Ghanaian");
        employees.add(employee);

      //Adding second employee
       Employee employee=new Employee("1","Akuah","Morrison","1984-02-04","Female","Ghanaian");
         employees.add(employee);

        StorageUtil.employees=employees;
    }

ตอนนี้คุณสามารถรับค่าของ StorageUtil.employees จากทุกที่ โชคดี!


0

ทางออกของฉันคือการเขียนวิธีคงที่ภายในส่วน:

public TheFragment setData(TheData data) {
    TheFragment tf = new TheFragment();
    tf.data = data;
    return tf;
}

วิธีนี้ฉันมั่นใจว่าข้อมูลทั้งหมดที่ฉันต้องการอยู่ใน Fragment ก่อนการดำเนินการอื่น ๆ ที่เป็นไปได้ซึ่งอาจจำเป็นต้องทำงานกับมัน ในความคิดของฉันมันดูสะอาดกว่าด้วย


1
ดีถ้า TheData ไม่ปลอดภัยกระทู้ทำให้คงที่ไม่จำเป็นต้องปกป้องคุณจากปัญหาด้าย ระวังด้วยว่า คงที่ไม่ด้ายปลอดภัยโดยธรรมชาติ
Martin Marconcini

0

ฉันพบปัญหาที่คล้ายกันขณะใช้ส่วนประกอบสถาปัตยกรรมการนำทางล่าสุด ลองใช้โค้ดที่กล่าวถึงด้านบนด้วยการส่งบันเดิลจากกิจกรรมการโทรของฉันไปที่ Fragment

ทางออกที่ดีที่สุดตามแนวโน้มการพัฒนาล่าสุดใน Android คือการใช้ View Model (ส่วนหนึ่งของ Android Jetpack)

สร้างและเริ่มต้นคลาส ViewModel ในกิจกรรมหลักโปรดทราบว่า ViewModel นี้จะต้องมีการแบ่งปันระหว่างกิจกรรมและส่วน

ในตอนนี้ภายใน onViewCreated () ของแฟรกเมนต์ให้เตรียมข้อมูลเบื้องต้น ViewModel และการตั้งค่า Observers เดียวกันเพื่อฟังฟิลด์ ViewModel

นี่คือการสอนที่มีประโยชน์และเจาะลึกหากคุณต้องการ

https://medium.com/mindorks/how-to-communicate-between-fragments-and-activity-using-viewmodel-ca733233a51c


-4

ในกิจกรรมของคุณประกาศตัวแปรคงที่

public static HashMap<String,ContactsModal> contactItems=new HashMap<String, ContactsModal>();

จากนั้นในส่วนของคุณจะชอบทำตาม

ActivityName.contactItems.put(Number,contactsModal);

มันจะทำงาน แต่ไม่แนะนำ ในฐานะสมาชิกแบบคงที่จะยังคงอยู่ในหน่วยความจำยกเว้นว่าแอพถูกบังคับให้ปิดจากแอพล่าสุด ดังนั้นในกรณีเช่นนี้คุณควรใช้สมาชิกแบบสแตติกเมื่อคุณต้องการในกิจกรรมมากมายตลอดทั้งแอพ
M Shaban Ali
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.