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