วิธีส่งค่าระหว่าง Fragments


109

ฉันค่อนข้างใหม่กับการใช้ Fragments

ฉันแค่พยายามสร้างแอปพลิเคชันตัวอย่างง่ายๆที่ใช้ Fragments สถานการณ์ของฉันคือฉันมีสองกิจกรรมโดยมีหนึ่งส่วนในแต่ละกิจกรรม ส่วนแรกมีข้อความแก้ไขและปุ่ม ส่วนที่สองมีมุมมองข้อความ เมื่อฉันป้อนชื่อในข้อความแก้ไขและคลิกที่ปุ่ม textview ในส่วนที่สองควรแสดงชื่อที่ป้อนในข้อความแก้ไขของส่วนแรก

ฉันสามารถส่งค่าจากส่วนแรกไปยังกิจกรรมของมันแล้วจากกิจกรรมนั้นไปยังกิจกรรมที่สอง ตอนนี้ฉันจะใช้ค่านี้ภายในส่วนที่สองได้อย่างไร

นี่คือรหัส Java :::

package com.example.fragmentexample;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Fragment_1 extends Fragment{

    OnFragmentChangedListener mCallback;

    // Container Activity must implement this interface
    public interface OnFragmentChangedListener {
        public void onButtonClicked(String name);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnFragmentChangedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub      

        View view = inflater.inflate(R.layout.fragment_fragment_1, container, false);

        final EditText edtxtPersonName_Fragment = (EditText) view.findViewById(R.id.edtxtPersonName);
        Button btnSayHi_Fragment = (Button) view.findViewById(R.id.btnSayHi);

        btnSayHi_Fragment.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                String name = edtxtPersonName_Fragment.getText().toString();

                FragmentManager fm = getFragmentManager();
                Fragment_2 f2 = (Fragment_2) fm.findFragmentById(R.id.fragment_content_2);

                Activity activity = getActivity();

                if(activity != null)
                {
                    Toast.makeText(activity, "Say&ing Hi in Progress...", Toast.LENGTH_LONG).show();
                }


                if(f2 != null && f2.isInLayout())
                {
                    f2.setName(name);
                }
                else
                {
                    mCallback.onButtonClicked(name);
                }
            }
        });

        return view;


    }

}

MainActivity Java

package com.example.fragmentexample;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;

import android.view.Choreographer.FrameCallback;
import android.view.Menu;

public class MainActivity extends Activity implements Fragment_1.OnFragmentChangedListener {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public void onButtonClicked(String name) {
        // TODO Auto-generated method stub

        Intent i = new Intent(this, SecondActivity.class);
        i.putExtra("", name);
        startActivity(i);
    }

}

SecondActivity Java

package com.example.fragmentexample;

import android.app.Activity;
import android.os.Bundle;

public class SecondActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_second);

        Bundle b = getIntent().getExtras();

        Fragment_2 f2 = new Fragment_2();
        f2.setArguments(b);
    }
}

Fragment_2 Java

package com.example.fragmentexample;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Fragment_2 extends Fragment{

    View view;
    TextView txtName;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub

        view = inflater.inflate(R.layout.fragment_fragment_2, container, false);

            // Exception at this line
        String name = getArguments().getString("message");
        txtName = (TextView) view.findViewById(R.id.txtViewResult);
        txtName.setText(name);

        return view;
    }

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);       
    }

    public void setName(String name)
    {   
        txtName.setText("Hi " + name);
    }

}

ฉันได้รับข้อยกเว้นต่อไปนี้ :::

04-16 18:10:24.573: E/AndroidRuntime(713): FATAL EXCEPTION: main
04-16 18:10:24.573: E/AndroidRuntime(713): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragmentexample/com.example.fragmentexample.SecondActivity}: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1815)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1831)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.access$500(ActivityThread.java:122)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1024)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.os.Looper.loop(Looper.java:132)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.main(ActivityThread.java:4123)
04-16 18:10:24.573: E/AndroidRuntime(713):  at java.lang.reflect.Method.invokeNative(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713):  at java.lang.reflect.Method.invoke(Method.java:491)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
04-16 18:10:24.573: E/AndroidRuntime(713):  at dalvik.system.NativeStart.main(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:688)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:724)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:391)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:347)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:223)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.setContentView(Activity.java:1786)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.example.fragmentexample.SecondActivity.onCreate(SecondActivity.java:13)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.performCreate(Activity.java:4397)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1779)
04-16 18:10:24.573: E/AndroidRuntime(713):  ... 11 more
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: java.lang.NullPointerException
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.example.fragmentexample.Fragment_2.onCreateView(Fragment_2.java:24)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:754)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:956)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1035)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.onCreateView(Activity.java:4177)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)
04-16 18:10:24.573: E/AndroidRuntime(713):  ... 21 more

ฉันจะรับค่าจากบันเดิลใน SecondActivity.java ไปยัง Fragment_2.Java ได้อย่างไร


โปรดเน้นส่วนที่ ru ได้รับปัญหา
Nikhil Agrawal

วิธีแก้ปัญหาด้วยวิธีง่ายๆ: stackoverflow.com/a/59332751/10201722
Adil Siddiqui

คำตอบ:


203

ขั้นตอนที่ 1ส่งข้อมูลจากส่วนย่อยไปยังกิจกรรม

Intent intent = new Intent(getActivity().getBaseContext(),
                        TargetActivity.class);
                intent.putExtra("message", message);
                getActivity().startActivity(intent);

ขั้นตอนที่ 2รับข้อมูลนี้ในกิจกรรม:

Intent intent = getIntent();
String message = intent.getStringExtra("message");

ขั้นตอนที่ 3 . ในการส่งข้อมูลจากกิจกรรมไปยังกิจกรรมอื่นให้เป็นไปตามแนวทางปกติ

Intent intent = new Intent(MainActivity.this,
                        TargetActivity.class);
                intent.putExtra("message", message);
                startActivity(intent);

ขั้นตอนที่ 4เพื่อรับข้อมูลนี้ในกิจกรรม

     Intent intent = getIntent();
  String message = intent.getStringExtra("message");

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

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

และรับเป็นส่วนย่อยในเมธอด Fragment onCreateView:

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

    return inflater.inflate(R.layout.fragment, container, false);
    }

2
ฉันลองขั้นตอนที่ 5 แล้วฉันกำลังเรียก listactivity จากแฟรกเมนต์และหลังจากเลือกไอเท็มจากกิจกรรมนั้นฉันต้องการกลับมาในแฟรกเมนต์พร้อมชื่อไฟล์ที่เลือก แต่มันไม่ได้ผลมันทำให้ฉันมีข้อยกเว้น Nullpointer ที่ onCreateView มีวิธีแก้ปัญหานี้ไหม นี่คือคำถามของฉันstackoverflow.com/questions/18208771/…
OnkarDhane

ฉันจะใส่ POJO ที่นี่ได้อย่างไร bundle.putString("message", "From Activity");
jeet.chanchawat

31
มีใครรังเกียจไหมที่ทำเรื่องแบบนี้
Ed Lee

1
แน่นอน Eddie นี่ไม่ใช่วิธีที่ถูกต้อง ควรใช้อินเทอร์เฟซเพื่อสื่อสารระหว่างชิ้นส่วนผ่านกิจกรรมคอนเทนเนอร์
Kaveesh Kanwal

เกี่ยวกับการใช้อินเทอร์เฟซเพื่อสื่อสารระหว่าง
Andre L Torres

49

ตามที่ระบุไว้ในไซต์ของนักพัฒนา

บ่อยครั้งที่คุณต้องการให้ Fragment หนึ่งสื่อสารกับอีกชิ้นหนึ่งเช่นเปลี่ยนเนื้อหาตามเหตุการณ์ของผู้ใช้ การสื่อสารจาก Fragment-to-Fragment ทั้งหมดทำผ่านกิจกรรมที่เกี่ยวข้อง สองชิ้นส่วนไม่ควรสื่อสารโดยตรง

การสื่อสารระหว่างชิ้นส่วนควรทำผ่านกิจกรรมที่เกี่ยวข้อง

มีส่วนประกอบดังต่อไปนี้:

กิจกรรมโฮสต์แฟรกเมนต์และอนุญาตการสื่อสารแฟรกเมนต์

Fragment คือแฟรกเมนต์แรกที่จะส่งข้อมูล

FragmentB ส่วนที่สองซึ่งจะรับข้อมูลจากFragmentA

การใช้งานของ FragmentA คือ:

public class FragmentA extends Fragment 
{
    DataPassListener mCallback;
    
    public interface DataPassListener{
        public void passData(String data);
    }

    @Override
    public void onAttach(Context context) 
    {
        super.onAttach(context);
        // This makes sure that the host activity has implemented the callback interface
        // If not, it throws an exception
        try 
        {
            mCallback = (OnImageClickListener) context;
        }
        catch (ClassCastException e) 
        {
            throw new ClassCastException(context.toString()+ " must implement OnImageClickListener");
        }
    }
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) 
    {
        // Suppose that when a button clicked second FragmentB will be inflated
        // some data on FragmentA will pass FragmentB
        // Button passDataButton = (Button).........
        
        passDataButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (view.getId() == R.id.passDataButton) {
                    mCallback.passData("Text to pass FragmentB");
                }
            }
        });
    }
}

การใช้งาน MainActivity คือ:

public class MainActivity extends ActionBarActivity implements DataPassListener{
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        if (findViewById(R.id.container) != null) {
            if (savedInstanceState != null) {
                return;
            }
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new FragmentA()).commit();
        }
    }
    
    @Override
    public void passData(String data) {
        FragmentB fragmentB = new FragmentB ();
        Bundle args = new Bundle();
        args.putString(FragmentB.DATA_RECEIVE, data);
        fragmentB .setArguments(args);
        getFragmentManager().beginTransaction()
            .replace(R.id.container, fragmentB )
            .commit();
    }
}

การใช้งาน FragmentB คือ:

public class FragmentB extends Fragment{
    final static String DATA_RECEIVE = "data_receive";
    TextView showReceivedData;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_B, container, false);
        showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
    }
    
    @Override
    public void onStart() {
        super.onStart();
        Bundle args = getArguments();
        if (args != null) {
            showReceivedData.setText(args.getString(DATA_RECEIVE));
        }
    }
}

หวังว่านี่จะช่วยได้ ..


4
OnImageClickListener คืออะไรที่นี่? และมันถูกส่งไปยังตัวแปร DataPassListener อย่างไร?
Harsha

ฉันพบว่ามันคือ "DataPassListener" ฉันใช้งานได้ แต่พบได้เนื่องจากทุกครั้งที่คลิกปุ่มข้อมูลจะถูกส่ง เมื่อส่งไปแล้วจะแทนที่แฟรกเมนต์ ซึ่งหมายความว่ารายการจะได้รับการต่ออายุทุกครั้ง ดังนั้นการไม่เก็บรายชื่อสิ่งของไว้ในหน่วยความจำ
wesley

44

// ใน Fragment_1.java

Bundle bundle = new Bundle();
bundle.putString("key","abc"); // Put anything what you want

Fragment_2 fragment2 = new Fragment_2();
fragment2.setArguments(bundle);

getFragmentManager()
      .beginTransaction()
      .replace(R.id.content, fragment2)
      .commit();

// ใน Fragment_2.java

Bundle bundle = this.getArguments();

if(bundle != null){
     // handle your code here.
}

หวังว่านี่จะช่วยคุณได้


1
คำตอบที่สะอาดเพื่อแสดงประเด็นหลัก ใช้putString(หรือputInt) คือคำตอบ!
Mehdi Dehghani

22

จากนักพัฒนาเว็บไซต์ :

บ่อยครั้งที่คุณต้องการให้ Fragment หนึ่งสื่อสารกับอีกชิ้นหนึ่งเช่นเปลี่ยนเนื้อหาตามเหตุการณ์ของผู้ใช้ การสื่อสารจาก Fragment-to-Fragment ทั้งหมดทำผ่านกิจกรรมที่เกี่ยวข้อง สองชิ้นส่วนไม่ควรสื่อสารโดยตรง

คุณสามารถสื่อสารระหว่างชิ้นส่วนด้วยความช่วยเหลือของกิจกรรม คุณสามารถสื่อสารระหว่างกิจกรรมและส่วนย่อยโดยใช้สิ่งนี้วิธีการ

กรุณาตรวจสอบนี้ลิงค์


ลิงก์ที่สองที่คุณให้ไว้แสดงวิธีการสื่อสารระหว่างส่วนต่างๆเมื่ออยู่ในกิจกรรมเดียวกัน ฉันจะสื่อสารได้อย่างไรเมื่อทั้งสองอยู่ในกิจกรรมที่แตกต่างกัน
Vamsi Challa

5

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

DataCacheดังนั้นหากโครงการของคุณเป็นเรื่องง่ายและพยายามที่จะใช้ นั่นเป็นวิธีที่ง่ายมากในการส่งผ่านข้อมูล อ้างอิง: Github project CachePot

1-ตั้งค่านี้เป็น View หรือ Activity หรือ Fragment ซึ่งจะส่งข้อมูล

DataCache.getInstance().push(obj);

2- รับข้อมูลที่ใดก็ได้เช่นด้านล่าง

public class MainFragment extends Fragment
{
    private YourObject obj;

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

        obj = DataCache.getInstance().pop(YourObject.class);

    }//end onCreate()
}//end class MainFragment

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

4

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

ในโซลูชันนี้แฟรกเมนต์ที่เกี่ยวข้องกับการสื่อสารแชร์อ็อบเจ็กต์ viewmodel เดียวกันซึ่งเชื่อมโยงกับวงจรชีวิตของกิจกรรม อ็อบเจ็กต์โมเดลมุมมองมีอ็อบเจ็กต์ liveata แฟรกเมนต์หนึ่งชุดข้อมูลที่จะส่งต่อไปยังอ็อบเจ็กต์ liveata และผู้สังเกตการณ์แฟรกเมนต์ที่สองอาศัยการเปลี่ยนแปลงและรับข้อมูล

นี่คือตัวอย่างที่สมบูรณ์http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel


3

ส่งผ่านข้อโต้แย้งระหว่างส่วนย่อย การตอบคำถามนี้ค่อนข้างช้า แต่อาจช่วยใครบางคนได้! Fragment_1.java

Bundle i = new Bundle(); 
            i.putString("name", "Emmanuel");

            Fragment_1 frag = new Fragment_1();
            frag.setArguments(i);
            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame
                            , new Fragment_2())
                    .commit();

จากนั้นในของFragment_2.javaคุณคุณจะได้รับพารามิเตอร์ตามปกติภายในonActivityCreated เช่นของคุณ

 Intent intent = getActivity().getIntent();
    if (intent.getExtras() != null) {
        String name =intent.getStringExtra("name");
    }

3

ฉันคิดว่าวิธีที่ดีในการแก้ปัญหานี้คือการใช้อินเทอร์เฟซที่กำหนดเอง

สมมติว่าคุณมีเศษสองส่วน (A และ B) ซึ่งอยู่ในกิจกรรมเดียวกันและคุณต้องการส่งข้อมูลจาก A ถึง B

อินเตอร์เฟซ :

public interface OnDataSentListener{
    void onDataSent(Object data);
}

กิจกรรม:

    public class MyActivity extends AppCompatActivity{

            private OnDataSentListener onDataSentListener;

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

                FragmentTransaction trans = getFragmentManager().beginTransaction();

                FragmentA fa = new FragmentA();
                FragmentB fb = new FragmentB();

               fa.setOnDataSentListener(new Listeners.OnDataSentListener() {
                    @Override
                    public void onDataSent(Object data) {
                         if(onDataSentListener != null)  onDataSentListener.onDataSent(data);
                    }
               });

                transaction.add(R.id.frame_a, fa);
                transaction.add(R.id.frame_b, fb);

                transaction.commit();
            }

            public void setOnDataSentListener(OnDataSentListener listener){
                this.onDataSentListener = listener;
            }
        }

ส่วน A:

public class FragmentA extends Fragment{

    private OnDataSentListener onDataSentListener;

    private void sendDataToFragmentB(Object data){
        if(onDataSentListener != null) onDataSentListener.onDataSent(data);
    }

    public void setOnDataSentListener(OnDataSentListener listener){
        this.onDataSentListener = listener;
    }
}

ส่วน B:

public class FragmentB extends Fragment{

    private void initReceiver(){
        ((MyActivity) getActivity()).setOnDataSentListener(new OnDataSentListener() {
            @Override
            public void onDataSent(Object data) {
                //Here you receive the data from fragment A
            }
        });
    }
}

2

การสื่อสารระหว่างชิ้นส่วนมีความซับซ้อนพอสมควร (ฉันคิดว่าแนวคิดของผู้ฟังค่อนข้างท้าทายในการนำไปใช้)

เป็นเรื่องปกติที่จะใช้ "Event Bus" เพื่อสรุปการสื่อสารเหล่านี้นี่คือไลบรารีของบุคคลที่สามที่ดูแลการสื่อสารนี้ให้คุณ

'Otto' เป็นสิ่งที่มักใช้ในการทำเช่นนี้และอาจคุ้มค่าที่จะดู: http://square.github.io/otto/


2

การส่งผ่านข้อมูลจาก Fragment ไปยัง Fragment อื่น

  • จาก Fragment แรก

    // Set data to pass
    MyFragment fragment = new MyFragment(); //Your Fragment
    Bundle bundle = new Bundle();
    bundle.putInt("year", 2017)  // Key, value
    fragment.setArguments(bundle); 
    // Pass data to other Fragment
    getFragmentManager()
     .beginTransaction()
     .replace(R.id.content, fragment)
     .commit(); 
  • ในส่วนที่สอง

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
    
         Bundle bundle = this.getArguments();
         if (bundle != null) {
             Int receivedYear = bundle.getInt("year", ""); // Key, default value
         } 
    }

1

การใช้งานที่เรียบง่ายนี้ช่วยในการส่งผ่านข้อมูลระหว่างชิ้นส่วนด้วยวิธีง่ายๆ คิดว่าคุณต้องการส่งผ่านข้อมูลจาก "Frgment1" ไปยัง "Fragment2"

ใน Fragment1 (ตั้งค่าข้อมูลที่จะส่ง)

 Bundle bundle = new Bundle();
 bundle.putString("key","Jhon Doe"); // set your parameteres

 Fragment2 nextFragment = new Fragment2();
 nextFragment.setArguments(bundle);

 FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
 fragmentManager.beginTransaction().replace(R.id.content_drawer, nextFragment).commit();

ในเมธอด Fragment2 onCreateView (รับพารามิเตอร์)

String value = this.getArguments().getString("key");//get your parameters
Toast.makeText(getActivity(), value+" ", Toast.LENGTH_LONG).show();//show data in tost

ในแอปของฉันฉันพยายามทำให้มันใช้งานได้ แต่แม้ว่าจะมีการส่งผ่านค่า แต่ก็ไม่ได้แสดงบน fragment2 ฉันคิดว่าฉันทำผิดพลาดในการตั้งค่า Rid.content_drawer ใครช่วยแนะนำฉันได้ไหมว่าอะไรเป็นตัวระบุที่ถูกต้องสำหรับ R.id.content_drawer ด้วยตัวอย่าง. xml
เหยี่ยว

1

ทาง Kotlin

ใช้สิ่งที่SharedViewModelเสนอในเอกสารของ ViewModel อย่างเป็นทางการ

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

จุดปวดทั่วไปนี้สามารถแก้ไขได้โดยใช้ออบเจ็กต์ ViewModel แฟรกเมนต์เหล่านี้สามารถแชร์ ViewModel โดยใช้ขอบเขตกิจกรรมเพื่อจัดการการสื่อสารนี้

ขั้นแรกให้ใช้fragment-ktxเพื่อสร้างอินสแตนซ์ viewmodel ของคุณได้ง่ายขึ้น

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.2.2"
} 

จากนั้นคุณเพียงแค่ใส่ข้อมูลที่คุณจะแชร์กับส่วนอื่น ๆ ภายใน viewmodel

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

จากนั้นในการดำเนินการให้เสร็จสิ้นให้สร้างอินสแตนซ์ viewModel ของคุณในแต่ละส่วนและตั้งค่าของ selectedจากส่วนที่คุณต้องการตั้งค่าข้อมูล

ส่วนก

class MasterFragment : Fragment() {

    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
        model.select(item)
      }

    }
}

จากนั้นเพียงแค่ฟังค่านี้ที่ปลายทาง Fragment ของคุณ

ส่วน B

 class DetailFragment : Fragment() {

        private val model: SharedViewModel by activityViewModels()

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
                // Update the UI
            })
        }
    }

คุณสามารถทำได้ในทางตรงกันข้าม


0

โซลูชันการทำงาน 100%: (หากช่วยได้อย่าลืมกดโหวต)

ในส่วนแรกของคุณให้ใส่รหัสชิ้นนี้:

    editprofile.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Fragment_editprofile Fragment = new Fragment_editprofile();
.
.
.
.
.


                Fragment.getintentdetails(tv_name.getText().toString(),
                            tv_mob.getText().toString(), tv_email.getText().toString(), tv_dob.getText().toString(),
                            tv_gender.getText().toString(), photointent);

                }
            });

ใน Second Fragment ให้ทำตามขั้นตอนด้านล่าง:

public void getintentdetails(String name, String mobile, String email, String dob, String gender,
                                 String photointent) {

        this.name_str= name;
        this.mob_str= mobile;
        this.email_str= email;
        this.dob_str= dob;
        this.gender_str= gender;
        this.photo_str= photointent;

    }

จากนั้นกำหนดตัวแปรที่ระดับชั้น:

String name_str, mob_str, dob_str, photo_str, email_str, gender_str;

จากนั้นสร้างวิธีอื่นในส่วนที่สองเพื่อตั้งค่า:

  setexistingdetails();


private void setexistingdetails() {

        if(!name_str.equalsIgnoreCase(""))
            (et_name).setText(name_str);
        if(!mob_str.equalsIgnoreCase(""))
            et_mobile.setText(mob_str);
        if(!email_str.equalsIgnoreCase(""))
            email_et.setText(email_str);
        if(!dob_str.equalsIgnoreCase(""))
            dob_et.setText(dob_str);
        if(!gender_str.equalsIgnoreCase("")){
            if (gender_str.equalsIgnoreCase("m")){
                male_radio.setChecked(true);
            }else {
                female_radio.setChecked(true);
            }
        }
        if(!photo_str.equalsIgnoreCase("")){
            try {
                Picasso.get().load(Const.BASE_PATH+"include/sub-domain/GENIUS/"+photo_str).into(adminpropic_edit);
            } catch (Exception e) {            }
        }
    }

0

คุณสามารถบรรลุเป้าหมายของคุณโดยViewModelและข้อมูลสดซึ่งเป็นที่ล้างโดยArnav ราว ตอนนี้ฉันวางตัวอย่างเพื่อให้ชัดเจนมากขึ้น

ครั้งแรกที่สันนิษฐานว่าเป็นชื่อViewModelSharedViewModel.java

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }
    public LiveData<Item> getSelected() {
        return selected;
    }
}

จากนั้นส่วนต้นทางคือMasterFragment.javaจากที่ที่เราต้องการส่งข้อมูล

public class MasterFragment extends Fragment {
    private SharedViewModel model;

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {

            // Data is sent

            model.select(item);
        });
    }
}

และสุดท้ายส่วนปลายทางคือDetailFragment.javaตำแหน่งที่เราต้องการรับข้อมูล

public class DetailFragment extends Fragment {

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        model.getSelected().observe(getViewLifecycleOwner(), { item ->

           // Data is received 

        });
    }
}

0

ตกลงหลังจากขุดมากที่นี่ฉันพบวิธีแก้ปัญหาง่ายๆจริงๆแล้วคุณไม่ควรส่งผ่านข้อมูลจากส่วนหนึ่งไปยังส่วนย่อยเป็นความคิดที่ไม่ดีเสมอไปคุณสามารถส่งข้อมูลจากส่วน A ไปยังกิจกรรมและรับข้อมูลจากกิจกรรมในส่วน B

For Example
//fragment A
//your method that will be called in Main Activity for getting data from this fragment
public List<customDataModel> getlist(){
return mlist; //your custom list 
}
buttonopen.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //before calling  your new fragment, send a Broadcast signal to your main activity
 mContext.sendBroadcast(new Intent("call.myfragment.action"));
//here you are now changing the fragment
Fragment fragment1 = new VolunteerListDetailsFragment();

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment1);
            ft.commit();
        }
    });

// ในกิจกรรมหลัก

this.registerReceiver(mBroadcastReceiver, new IntentFilter("call.myfragment.action"));//this line should be in your onCreate method
   BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
//init the fragment A
FragmenA fragment =
                (FragmentA) getSupportFragmentManager().findFragmentById(R.id.content_frame);
        mlistdetails = fragment.getlist();//this is my method in fragmentA which is retuning me a custom list, init this list type in top of on create fragment


    }
};
//here you are creating method that is returning the list that you just recieved From fragmentA
public List<customDataModel> getcustomlist(){
return mlistdetails; //you are returning the same list that you recived from fragmentA
}

// ตอนนี้อยู่ใน FragmentB

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

    View rootView = (View) inflater.inflate(R.layout.vol_listdetails, container, false);

    mlistdetails=((MainActivity)getActivity()).getcustomlist();//here you are calling the method that you have created in Main Activity

    Toast.makeText(getActivity().getApplicationContext(), mlistdetails.get(0).getItemqty(), Toast.LENGTH_SHORT).show();
    return rootView;

}

-2

ฉันได้ทำสิ่งที่ง่ายมากสำหรับขอทานอย่างฉัน .. ฉันสร้าง textview ใน activity_main.xml ของฉันและใส่

id=index
visibility=invisible

จากนั้นฉันจะได้รับ textview นี้จากส่วนแรก

index= (Textview) getActivity().findviewbyid(R.id.index)
index.setText("fill me with the value")

จากนั้นในส่วนที่สองฉันจะได้รับค่า

index= (Textview) getActivity().findviewbyid(R.id.index)
String get_the_value= index.getText().toString();

หวังว่ามันจะช่วยได้!


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