Как передавать значения между фрагментами



Я довольно новичок в использовании фрагментов.



Я просто пытаюсь построить простой пример приложения, которое использует фрагменты. Мой сценарий заключается в том, что у меня есть два действия с одним фрагментом внутри каждого действия. Первый фрагмент имеет edittext и кнопку. Второй фрагмент имеет текстовое представление. Когда я ввожу имя в 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);
}
}


Фрагмент_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.access0(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 в Фрагмент_2.Ява?

795   12  

12 ответов:

Шаг 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 чтобы получить эти данные в activity

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

Шаг 5. из действия вы можете отправить данные на фрагмент с намерением как:

Bundle bundle=new Bundle();
bundle.putString("message", "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("message");

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

как отмечено на сайте разработчика

часто вы хотите, чтобы один фрагмент связывался с другим, например, чтобы изменить содержимое на основе события пользователя. Вся связь фрагмент-фрагмент осуществляется через соответствующую деятельность. Два фрагмента никогда не должны общаться напрямую.

связь между фрагментами должна осуществляться через соответствующую деятельность.

давайте иметь следующие компоненты:

действие хосты фрагменты и разрешить фрагменты связи

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

I надеюсь, это поможет..

с разработчики сайт:

часто вы хотите, чтобы один фрагмент связывался с другим, например, чтобы изменить содержимое на основе события пользователя. Вся связь фрагмент-фрагмент осуществляется через соответствующую деятельность. Два фрагмента никогда не должны общаться напрямую.

вы можете общаться между фрагментами с помощью своей деятельности. Вы можете общаться между активностью и фрагментом с помощью этой подход.

пожалуйста, проверьте этой ссылке также.

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

надеюсь, что это поможет вам.

сначала все ответы правильно, вы можете передать данные кроме пользовательских объектов с помощью Intent. Если вы хотите передать пользовательские объекты, вы должны реализовать Serialazable или Parcelable для вашего пользовательского класса объектов. Я думал, что это слишком сложно...

так что если ваш проект прост, попробуйте использовать DataCache. Это обеспечивает супер простой способ передачи данных. Ref:GitHub project 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

общение между фрагментами довольно сложно (я нахожу концепцию слушателей немного сложной для реализации).

обычно для абстрагирования этих сообщений используется "шина событий". Это сторонняя библиотека, которая заботится об этом сообщении для вас.

"Отто" - это тот, который часто используется для этого, и, возможно, стоит изучить: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 вы можете получить paramaters нормально в пределах вашего onActivityCreated е.г

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

эта простая реализация помогает передавать данные между фрагментами простым способом. Думаю, вы хотите передать данные из 'Frgment1' в 'Fragment2'

в Фрагмент1 (установить данные для отправки)

 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 (Get parameteres)

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

передача данных от фрагмента к другому фрагменту

  • из первого фрагмента

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

последнее решение для передачи данных между фрагментами может быть реализовано с помощью архитектурных компонентов android, таких как ViewModel и LiveData. С помощью этого решения вам не нужно определять интерфейс для связи и вы можете получить преимущества использования viewmodel как выживание данных из-за изменений конфигурации.

в этом решении фрагменты, участвующие в связи, совместно используют один и тот же объект viewmodel, который привязан к их жизненному циклу активности. Модель представления объект содержит объект livedata. Один фрагмент задает данные для передачи на объект livedata, а второй фрагмент наблюдатели livedata изменяют и получают данные.

вот полный пример http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel

Я думаю, что хороший способ решить эту проблему заключается в использовании пользовательский интерфейс.

допустим, у вас есть два фрагмента (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
            }
        });
    }
}

Я сделал что-то очень легко для нищих, как я.. я сделал 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();

надеюсь, что это помогает!

Comments

    Ничего не найдено.