Programing

프래그먼트간에 값을 전달하는 방법

lottogame 2020. 8. 15. 09:46
반응형

프래그먼트간에 값을 전달하는 방법


저는 Fragments를 처음 사용합니다.

Fragments를 사용하는 간단한 샘플 애플리케이션을 빌드하려고합니다. 내 시나리오는 각 활동 내에 하나의 조각이있는 두 개의 활동이 있습니다. 첫 번째 조각에는 편집 텍스트와 버튼이 있습니다. 두 번째 조각에는 텍스트보기가 있습니다. edittext에 이름을 입력하고 버튼을 클릭하면 두 번째 조각의 textview에 첫 번째 조각의 edittext에 입력 된 이름이 표시됩니다.

첫 번째 조각의 값을 해당 활동으로 보낸 다음 해당 활동에서 두 번째 활동으로 보낼 수있었습니다. 이제 두 번째 조각 내에서이 값을 어떻게 사용합니까?

다음은 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로 값을 어떻게 가져 옵니까?


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 단계. Activity에서 다음과 같은 인 텐트를 사용하여 데이터를 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);
    }

개발자 사이트에서 언급 한대로

예를 들어 사용자 이벤트를 기반으로 콘텐츠를 변경하기 위해 종종 하나의 Fragment가 다른 Fragment와 통신하기를 원할 것입니다. 모든 Fragment-to-Fragment 통신은 관련 활동을 통해 이루어집니다. 두 조각은 직접 통신해서는 안됩니다.

프래그먼트 간의 통신은 연관된 활동을 통해 수행되어야합니다.

다음 구성 요소가 있습니다.

활동 은 조각을 호스팅하고 조각 통신을 허용합니다.

Fragment 데이터를 보낼 첫 번째 조각

FragmentA 에서 데이터를 수신 할 FragmentB 두 번째 조각

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

도움이 되었으면합니다 ..


// 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.
}

도움이 되었기를 바랍니다.


에서 개발자 웹 사이트 :

예를 들어 사용자 이벤트를 기반으로 콘텐츠를 변경하기 위해 종종 하나의 Fragment가 다른 Fragment와 통신하기를 원할 것입니다. 모든 Fragment-to-Fragment 통신은 관련 활동을 통해 이루어집니다. 두 조각은 직접 통신해서는 안됩니다.

활동의 도움으로 조각간에 통신 할 수 있습니다. 접근 방식을 사용하여 활동과 조각간에 통신 할 수 있습니다 .

링크도 확인하십시오 .


먼저 모든 대답이 맞습니다 Intent. 을 사용하여 사용자 지정 개체를 제외한 데이터를 전달할 수 있습니다 . 사용자 지정 개체를 전달하려면 Serialazable또는 Parcelable사용자 지정 개체 클래스 를 구현 해야합니다. 너무 복잡하다고 생각했는데 ...

따라서 프로젝트가 간단하다면 DataCache. 그것은 데이터를 전달하는 매우 간단한 방법을 제공합니다. 참고 : Github 프로젝트 CachePot

1- 데이터를 보낼보기 또는 활동 또는 조각으로 설정합니다.

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

조각 간 데이터 전달을위한 최신 솔루션은 ViewModel 및 LiveData와 같은 Android 아키텍처 구성 요소를 사용하여 구현할 수 있습니다. 이 솔루션을 사용하면 통신을위한 인터페이스를 정의 할 필요가 없으며 구성 변경으로 인한 데이터 생존과 같은 뷰 모델을 사용하는 이점을 얻을 수 있습니다.

이 솔루션에서 통신에 관련된 프래그먼트는 활동 라이프 사이클에 연결된 동일한 viewmodel 객체를 공유합니다. 보기 모델 개체에는 livedata 개체가 포함됩니다. 하나의 프래그먼트는 라이브 데이터 객체에 전달할 데이터를 설정하고 두 번째 프래그먼트 옵저버는 라이브 데이터를 변경하고 데이터를 수신합니다.

다음은 완전한 예입니다. http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel


프래그먼트 간의 통신은 상당히 복잡합니다 (리스너 개념을 구현하기가 약간 어렵습니다).

이러한 통신을 추상화하기 위해 '이벤트 버스'를 사용하는 것이 일반적입니다.이 통신을 처리하는 타사 라이브러리입니다.

'Otto'는이 작업을 수행하는 데 자주 사용되며 살펴볼 가치가 있습니다. http://square.github.io/otto/


조각 간 인수 전달. 이 질문에 답하기에는 상당히 늦었지만 누군가를 도울 수 있습니다!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");
    }

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

이 문제를 해결하는 좋은 방법은 사용자 정의 인터페이스를 사용하는 것입니다.

동일한 활동 내에있는 두 개의 조각 (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
            }
        });
    }
}

이 간단한 구현은 간단한 방법으로 조각간에 데이터를 전달하는 데 도움이됩니다. '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

나는 나 같은 초보자를 위해 정말 쉬운 것을 만들었다. 나는 내 activity_main.xml에 textview를 만들고

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

도움이 되길 바랍니다!

참고 URL : https://stackoverflow.com/questions/16036572/how-to-pass-values-between-fragments

반응형