在Android中将活动的数据发送到片段
我有两个class。 首先是活动,其次是我有一些edittexts的片段。 在活动中,我有一个与asynchronous任务和doInBackground
方法的子类,我得到了一些结果,我保存到variables。 我怎么能发送这个variables从子类“我的活动”这个片段?
从活动中发送数据意图为:
Bundle bundle = new Bundle(); bundle.putString("edttext", "From Activity"); // set Fragmentclass Arguments Fragmentclass fragobj = new Fragmentclass(); fragobj.setArguments(bundle);
并在片段onCreateView方法:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { String strtext = getArguments().getString("edttext"); return inflater.inflate(R.layout.fragment, container, false); }
您也可以从片段访问活动数据:
活动:
public class MyActivity extends Activity { private String myString = "hello"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); ... } public String getMyData() { return myString; } }
分段:
public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { MyActivity activity = (MyActivity) getActivity(); String myDataFromActivity = activity.getMyData(); return view; } }
我在这里find了很多答案@ stackoverflow.com,但绝对是这样的正确答案:
“从活动发送数据到Android中的片段”。
活动:
Bundle bundle = new Bundle(); String myMessage = "Stackoverflow is cool!"; bundle.putString("message", myMessage ); FragmentClass fragInfo = new FragmentClass(); fragInfo.setArguments(bundle); transaction.replace(R.id.fragment_single, fragInfo); transaction.commit();
分段:
读取片段中的值
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Bundle bundle = this.getArguments(); String myValue = bundle.getString("message"); ... ... ... }
要不就
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { String myValue = this.getArguments().getString("message"); ... ... ... }
这个答案可能为时已晚。 但对未来的读者会有帮助。
我有一些标准。 我已经编码从意图挑选文件。 并将选定的文件传递给特定的片段以供进一步处理。 我有很多具有文件拣选function的片段。 当时,每次检查条件得到的片段和传递值都相当恶心。 所以,我决定通过使用接口的值。
步骤1:在主要活动上创build界面。
public interface SelectedBundle { void onBundleSelect(Bundle bundle); }
第2步:在相同的活动中创build方法
public void setOnBundleSelected(SelectedBundle selectedBundle) { this.selectedBundle = selectedBundle; }
第3步:在同一个活动上创buildSelectedBundle引用
SelectedBundle selectedBundle;
第4步:需要初始化SelectedBundle引用,这是所有片段需要filepickerfunction。您将此代码放在您的片段onCreateView(..)
方法
((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() { @Override public void onBundleSelect(Bundle bundle) { updateList(bundle); } });
第5步:从MainActivity的onActivityResult,使用接口传递值到片段。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { selectedBundle.onBundleSelect(bundle); }
就这样。 在FragmentClass上实现你需要的每一个片段。 你很棒。 你已经完成了。 哇…
如果您将引用(具体子类)片段传递给asynchronous任务,则可以直接访问该片段。
将片段引用传递给asynchronous任务的一些方法:
- 如果你的asynchronous任务是一个完全成熟的类(
class FooTask extends AsyncTask
),然后将你的片段传递给构造函数。 - 如果你的asynchronous任务是一个内部类,只要在定义asynchronous任务的范围中声明一个最终的Fragmentvariables,或者作为外部类的一个字段。 你将能够从内部类访问。
使用Fragments(F)的基本思想是在Android应用程序中创build可重用的自持UI组件。 这些碎片被包含在活动中,并且存在从A→F和FA创build通信path方式的通用(最佳)方式,通过活动在FF之间进行通信是必须的,因为只有碎片变得分离和自我维持。
所以传递来自A – > F的数据将与ρяσѕρєяK所解释的相同。除了这个答案,在Activity中创buildFragments之后,我们也可以将数据传递给Fragments中的片段调用方法。
例如:
ArticleFragment articleFrag = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment); articleFrag.updateArticleView(position);
最好的和方便的方法是调用片段实例并在当时发送数据。 每个片段默认都有实例方法
例如:如果您的片段名称是MyFragment
所以你会从这样的活动中调用你的片段:
getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();
R.id.container是我的FrameLayout的一个id
所以在MyFragment.newInstance(“data1”,“data2”)你可以发送数据片段,并在你的片段,你在MyFragment newInstance(String param1,String param2)
public static MyFragment newInstance(String param1, String param2) { MyFragment fragment = new MyFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; }
然后在onCreate方法的片段,你会得到的数据:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } }
所以现在mParam1有data1,而mParam2有data2
现在你可以在你的片段中使用这个mParam1和mParam2 。
很老的post,我还敢添加一些对我有帮助的解释。
从技术上讲,你可以直接从活动中设置任意types的成员。
那么为什么捆绑?
原因很简单 – Bundle提供了统一的处理方式:
– 创build/打开片段
– 重新configuration(屏幕旋转) – 只需添加初始/更新捆绑到outState onSaveInstanceState()
– 在后台垃圾收集后的应用程序恢复(与重新configuration一样)。
你可以(如果你喜欢实验)在简单的情况下创build一个解决方法,但Bundle-approach只是看不到一个片段和一个背后的千片之间的区别 – 它保持简单和直接。
这就是为什么@Elenasys的答案是最优雅和最普遍的解决scheme。
这就是为什么@Martin给出的答案有缺陷
将数据从活动类发送到片段的更好方法是通过setter方法传递。 喜欢
FragmentClass fragmentClass = new FragmentClass(); fragmentClass.setMyList(mylist); fragmentClass.setMyString(myString); fragmentClass.setMyMap(myMap);
并从课堂上轻松获取这些数据。
从活动你发送数据与捆绑为:
Bundle bundle = new Bundle(); bundle.putString("data", "Data you want to send"); // Your fragment MyFragment obj = new MyFragment(); obj.setArguments(bundle);
并在片段onCreateView方法获取数据:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,`Bundle savedInstanceState) { String data = getArguments().getString("data");// data which sent from activity return inflater.inflate(R.layout.myfragment, container, false); }
如果一个activity
需要使一个fragment
在初始化之后执行一个动作,最简单的方法是让该activity
在fragment
实例上调用一个方法。 在fragment
中添加一个方法:
public class DemoFragment extends Fragment { public void doSomething(String param) { // do something in fragment } }
然后在activity
,使用fragment
pipe理器访问fragment
并调用method
:
public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DemoFragment fragmentDemo = (DemoFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentDemo); fragmentDemo.doSomething("some param"); } }
然后该activity
可以通过调用此method
直接与该fragment
进行通信。
有时你可以在你的活动中接收意图,你需要将信息传递给你的工作片段。
如果您需要启动片段,但是如果它仍然在工作,给定的答案是可以的, setArguments()
并不是非常有用。
如果传递的信息会导致与您的用户界面交互,则会出现另一个问题。 在这种情况下,你不能调用类似myfragment.passData()
东西,因为android会很快的告诉只有创build视图的线程可以与之交互。
所以我的build议是使用一个接收器。 这样,您可以从任何地方发送数据,包括活动,但作业将在片段的上下文中完成。
在你的片段的onCreate()
:
protected DataReceiver dataReceiver; public static final String REC_DATA = "REC_DATA"; @Override public void onCreate(Bundle savedInstanceState) { data Receiver = new DataReceiver(); intentFilter = new IntentFilter(REC_DATA); getActivity().registerReceiver(dataReceiver, intentFilter); } private class DataReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int data= intent.getIntExtra("data", -1); // Do anything including interact with your UI } }
在你的活动中:
// somewhere Intent retIntent = new Intent(RE_DATA); retIntent.putExtra("data", myData); sendBroadcast(retIntent);
您可以在片段中创build公共静态方法,您将获得该片段的静态引用,然后将数据传递给该函数,并将该数据设置为相同方法中的参数,并通过getArgument获取片段的oncreate方法的数据,并将该数据设置为本地variables。
最聪明的尝试和testing片段和活动之间传递数据的方式是创build一个variables,例如:
class StorageUtil { public static ArrayList<Employee> employees; }
然后将数据从片段传递到活动,我们在onActivityCreated方法中这样做:
//a field created in the sending fragment ArrayList<Employee> employees; @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); employees=new ArrayList(); //java 7 and above syntax for arraylist else use employees=new ArrayList<Employee>() for java 6 and below //Adding first employee Employee employee=new Employee("1","Andrew","Sam","1984-04-10","Male","Ghanaian"); employees.add(employee); //Adding second employee Employee employee=new Employee("1","Akuah","Morrison","1984-02-04","Female","Ghanaian"); employees.add(employee); StorageUtil.employees=employees; }
现在您可以从任何地方获得StorageUtil.employees的价值。 祝你好运!
我的解决scheme是在片段内写入一个静态方法:
public TheFragment setData(TheData data) { TheFragment tf = new TheFragment(); tf.data = data; return tf; }
这样我就可以肯定,我需要的所有数据都是在可能需要使用它的任何其他可能的操作之前的片段内。 在我看来,它看起来更干净。
检查这个答案,如果你想在数据创build后传递数据到https://stackoverflow.com/a/46467866/1594998
使用以下界面在活动和片段之间进行通信
public interface BundleListener { void update(Bundle bundle); Bundle getBundle(); }
或者使用以下这个通用监听器来进行使用接口的双向通信
/** * Created by Qamar4P on 10/11/2017. */ public interface GenericConnector<T,E> { T getData(); void updateData(E data); void connect(GenericConnector<T,E> connector); }
片段显示方法
public static void show(AppCompatActivity activity) { CustomValueDialogFragment dialog = new CustomValueDialogFragment(); dialog.connector = (GenericConnector) activity; dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment"); }
您也可以在onAttach(Context)
您的上下文转换为GenericConnector
在你的活动中
CustomValueDialogFragment.show(this);
在你的片段
... @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); connector.connect(new GenericConnector() { @Override public Object getData() { return null; } @Override public void updateData(Object data) { } @Override public void connect(GenericConnector connector) { } }); } ... public static void show(AppCompatActivity activity, GenericConnector connector) { CustomValueDialogFragment dialog = new CustomValueDialogFragment(); dialog.connector = connector; dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment"); }
注意:不要像"".toString().toString().toString();
办法。
添加到ρяσѕρєяK的答案。 在设置参数的同时,应该保持语句的执行顺序。 例如在答案序列中是:
Bundle bundle = new Bundle(); bundle.putString("edttext", "From Activity"); // set Fragmentclass Arguments Fragmentclass fragobj = new Fragmentclass(); fragobj.setArguments(bundle);
但是,如果您尝试首先分配片段,然后分配一个Bundle对象,并尝试将其设置为分配的片段的参数,则有时可能会在片段内的onCreateView方法中将其视为null。 例如,通过使用下面的代码段,有时候onCreateView中的getArguments可能会返回null。
容易出错的代码段:
Fragmentclass fragobj = new Fragmentclass(); Bundle bundle = new Bundle(); bundle.putString("edttext", "From Activity"); // set Fragmentclass Arguments fragobj.setArguments(bundle);
我在一段时间里面对同样的问题,但是当我改变陈述的顺序时,问题就解决了。 如果有人能给出一个坚实的理由,这将是很好的。 这很可能取决于执行时间。 更有经验的人应该给它背后的理由。