2つのクラスがあります。1つはアクティビティ、2つ目はフラグメントがあるフラグメントEditText
です。アクティビティでは、async-taskを持つサブクラスがあり、メソッドdoInBackground
では、結果を変数に保存します。この変数をサブクラス「my activity」からこのフラグメントに送信するにはどうすればよいですか?
2つのクラスがあります。1つはアクティビティ、2つ目はフラグメントがあるフラグメントEditText
です。アクティビティでは、async-taskを持つサブクラスがあり、メソッドdoInBackground
では、結果を変数に保存します。この変数をサブクラス「my activity」からこのフラグメントに送信するにはどうすればよいですか?
回答:
アクティビティから、次のような目的でデータを送信します。
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);
}
getArguments().getString(key)
また、フラグメントからアクティビティデータにアクセスできます。
アクティビティ:
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;
}
}
Bundle
。クラスを使用して情報を渡す方が適切です。または、そのgetMyData()
メソッドをインターフェイスから継承および実装し、Fragment
getActivityがinstanceof
でインターフェイスを返すかどうかを確認することもできますonAttach()
。
私はここ@ stackoverflow.comでたくさんの答えを見つけましたが、間違いなくこれは正しい答えです:
アクティビティ:
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");
...
...
...
}
この答えは手遅れかもしれません。しかし、それは将来の読者にとって有用でしょう。
いくつかの基準があります。意図からファイルを選択するようにコーディングしました。さらに選択したファイルを特定のフラグメントに渡してさらに処理します。ファイルピッキングの機能を持つ多くのフラグメントがあります。当時、状態をチェックしてフラグメントを取得して値を渡すたびに、かなり嫌です。だから、私はインターフェイスを使用して値を渡すことにしました。
手順1:メインアクティビティのインターフェイスを作成します。
public interface SelectedBundle {
void onBundleSelect(Bundle bundle);
}
ステップ2:同じアクティビティでSelectedBundle参照を作成する
SelectedBundle selectedBundle;
ステップ3:同じアクティビティでメソッドを作成する
public void setOnBundleSelected(SelectedBundle selectedBundle) {
this.selectedBundle = selectedBundle;
}
ステップ4:すべてフラグメントであるSelectedBundle参照を初期化する必要がありますfilepicker機能。このコードをフラグメントonCreateView(..)
メソッドに配置します。
((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
@Override
public void onBundleSelect(Bundle bundle) {
updateList(bundle);
}
});
ステップ5:私の場合、HomeActivityからイメージのUriをフラグメントに渡す必要があります。そこで、この機能をonActivityResultメソッドで使用しました。
MainActivityのonActivityResultから、インターフェースを使用して値をフラグメントに渡します。
注: ケースが異なる場合があります。あなたはあなたのHomeActivityからどこからでもそれを呼び出すことができます。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
selectedBundle.onBundleSelect(bundle);
}
それで全部です。FragmentClassで必要なすべてのフラグメントを実装します。あなたは素晴らしいです。あなたがやった。ワオ...
フラグメント(F)を使用する基本的な考え方は、Androidアプリケーションで再利用可能な自己維持UIコンポーネントを作成することです。これらのフラグメントはアクティビティに含まれており、A-> FとFAから通信パスを作成する一般的な(最良の)方法があります。フラグメントのみが分離されて自立するため、アクティビティを通じてFF間で通信する必要があります。
したがって、A-> Fからデータを渡すことは、ρяσѕρєяKで説明したものと同じになります。その答えに加えて、アクティビティ内でフラグメントを作成した後、フラグメントでメソッドを呼び出すフラグメントにデータを渡すこともできます。
例えば:
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、文字列パラメータ2)
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 をフラグメントで使用できます。
初心者のために、ここで最も支持されている2つの回答の違いは、フラグメントの使用方法が異なることで得られることを付け加えておきます。
渡すデータがあるJavaクラス内でフラグメントを使用する場合、最初の回答を適用してデータを渡すことができます。
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
ただし、たとえばタブ付きフラグメントに対してAndroid Studioによって提供されるデフォルトコードを使用する場合、このコードは機能しません。
(図に示すようにそれはあなたのFragmentClassesでデフォルトのPlaceholderFragmentを交換しても動作しません、あなたはのgetItemためのスイッチを(追加する新しい状況にFragmentPagerAdapterを修正する場合でも)とgetPageTitleための別のスイッチ()こちら)
警告:上記のクリップにはコードエラーがあります。これについては後で説明しますが、デフォルトのコードからタブ付きフラグメントの編集可能なコードに移行する方法を確認するのに役立ちます)。私の残りの回答は、そのクリップからのJavaクラスとxmlファイル(初心者シナリオによるタブ付きフラグメントの最初の使用を表す)を考慮すると、はるかに意味があります。
このページから最も賛成された回答が機能しない主な理由は、タブ付きフラグメントのデフォルトコードでは、フラグメントが別のJavaクラスで使用されているためです:FragmentPagerAdapter!
したがって、データを送信するために、MotherActivityでバンドルを作成し、回答2を使用してそれをFragmentPagerAdapterで渡すように誘惑されます。
それだけがまた間違っています。(おそらくあなたはそのようにそれを行うことができますが、それは本当に必要とされない単なる合併症です)
それを行うための正しい/より簡単な方法は、回答2を使用して、問題のフラグメントにデータを直接渡すことだと思います。はい、タブ付きフラグメントの場合、アクティビティとフラグメントの間に密接な結合がありますが、これは一種の予想です。MotherActivityのJavaクラス内にタブ付きフラグメントを作成することもお勧めします(MotherActivityの外部では決して使用されないため、サブクラスとして)-簡単です。MotherActivityのJavaクラス内に、次のように必要な数のフラグメントを追加するだけです。
public static class Tab1 extends Fragment {
public Tab1() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
return rootView;
}
}.
したがって、MotherActivityからそのようなフラグメントにデータを渡すには、母親のアクティビティのonCreateの上にプライベートの文字列/バンドルを作成する必要があります。フラグメントに渡すデータを入力して、それらをonCreateの後に作成されたメソッド(ここではgetMyData()と呼ばれます)。
public class MotherActivity extends Activity {
private String out;
private Bundle results;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mother_activity);
// for example get a value from the previous activity
Intent intent = getIntent();
out = intent.getExtras().getString("Key");
}
public Bundle getMyData() {
Bundle hm = new Bundle();
hm.putString("val1",out);
return hm;
}
}
次に、フラグメントクラスでgetMyDataを使用します。
public static class Tab1 extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public Tab1() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
TextView output = (TextView)rootView.findViewById(R.id.your_id_for_a_text_view_within_the_layout);
MotherActivity activity = (MotherActivity)getActivity();
Bundle results = activity.getMyData();
String value1 = results.getString("val1");
output.setText(value1);
return rootView;
}
}
データベースクエリがある場合、MotherActivityでそれらを実行することをお勧めします(そして、結果を上記のようにバンドル内のキーにアタッチされた文字列/整数として渡す)、タブ付きフラグメント内では、構文がより複雑になります(これはgetActivity ()たとえば、getIntentはgetActivity()。getIntent)になりますが、必要に応じて実行するオプションもあります。
初心者のための私のアドバイスは、小さなステップに焦点を当てることです。最初に、データを渡さずに、非常に単純なタブ付きアクティビティを開くという意図を持ちます。うまくいきますか?期待するタブが開きますか?そうでない場合、なぜですか?
それから始めて、このクリップに示されているようなソリューションを適用することで、何が欠けているかを確認してください。その特定のクリップでは、mainactivity.xmlは表示されません。それはきっとあなたを混乱させるでしょう。しかし、注意を払うと、たとえば、コンテキスト(tools:context)がxmlフラグメントファイルで間違っていることがわかります。各フラグメントXMLは、正しいフラグメントクラス(またはセパレーター$を使用したサブクラス)を指す必要があります。
また、メインアクティビティのJavaクラスで、tabLayout.setupWithViewPager(mViewPager)を追加する必要があることもわかります-TabLayout tabLayout =(TabLayout)findViewById(R.id.tabs); この行がないと、ビューは実際にはフラグメントのXMLファイルにリンクされませんが、メインアクティビティのxmlファイルのみが表示されます。
メインアクティビティのJavaクラスの行に加えて、メインアクティビティのXMLファイルでは、状況に合わせてタブを変更する必要があります(TabItemの追加や削除など)。メインアクティビティXMLにタブがない場合は、最初に作成したときに正しいアクティビティタイプを選択しなかった可能性があります(新しいアクティビティ-タブ付きアクティビティ)。
最後の3つの段落では、動画について説明します。つまり、メインアクティビティXMLと言うとき、それはビデオのメインアクティビティXMLであり、状況では、MotherActivity XMLファイルです。
フラグメント(の具体的なサブクラス)への参照を非同期タスクに渡すと、フラグメントに直接アクセスできます。
フラグメント参照を非同期タスクに渡すいくつかの方法:
class FooTask extends AsyncTask
)の場合は、フラグメントをコンストラクターに渡します。場合によっては、アクティビティでインテントを受け取ることができ、情報を作業フラグメントに渡す必要があります。
フラグメントを開始する必要がある場合、指定された回答は問題setArguments()
ありませんが、それでも機能する場合は、あまり役に立ちません。
渡された情報がUIとの対話を引き起こす場合、別の問題が発生します。その場合myfragment.passData()
、Androidはビューを作成したスレッドのみが対話できることをすばやく通知するため、次のようなものを呼び出すことはできません。
だから私の提案はレシーバーを使うことです。そうすれば、アクティビティを含め、どこからでもデータを送信できますが、ジョブはフラグメントのコンテキスト内で実行されます。
あなたのフラグメントでは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);
非常に古い投稿ですが、それでも私に役立つだろう少しの説明をあえて加えます。
技術的には、アクティビティのフラグメントに任意のタイプのメンバーを直接設定できます。
なぜバンドルなのか?
その理由は非常にシンプルです-バンドルは、処理するための統一された方法を提供します:
-フラグメントの作成/オープン
-再構成(画面回転)-onSaveInstanceState()のoutStateに初期/更新されたバンドルを追加するだけ
-バックグラウンドでガベージコレクションされた後のアプリの復元(再構成と同様)。
(実験が好きな場合は)簡単な状況で回避策を作成できますが、バンドルアプローチでは、バックスタックで1つのフラグメントと1000の違いが見られないだけです。シンプルで簡単です。@Elenasys
の答えが最もエレガントで普遍的なソリューションであるのはそのためです。そしてそれが@Martinの答えに落とし穴がある理由です
アクティビティクラスからフラグメントにデータを送信するためのより良いアプローチは、セッターメソッドを介して渡すことです。お気に入り
FragmentClass fragmentClass = new FragmentClass();
fragmentClass.setMyList(mylist);
fragmentClass.setMyString(myString);
fragmentClass.setMyMap(myMap);
クラスからこれらのデータを簡単に取得します。
Activity
あなたにバンドルを使用してデータを送信します。
Bundle bundle = new Bundle();
bundle.putString("data", "Data you want to send");
// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);
そして、Fragment
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
使用してにアクセスし、を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");
}
}
そして、はthisを呼び出すことでactivity
と直接通信できます。fragment
method
onCreateView
、フラグメントのメソッドに入る必要がないという意味で、本当に素晴らしいです。本当に役に立ちました
以下のインターフェースを使用して、アクティビティとフラグメントの間で通信します
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");
}
あなたはあなたにコンテキストをキャストすることができますGenericConnector
にonAttach(Context)
すぎ
あなたの活動で
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();
。
上記の方法のほとんどは機能しますが、この質問に遭遇しました。特にコンポーネント(アクティビティまたはフラグメント)が作成されていないシナリオでEvent Bus Libraryを使用できることを追加したいと思います。これは、Androidプロジェクトのすべてのサイズと多くの使用例に適しています。私はプレイストアで持っているいくつかのプロジェクトで個人的に使用しました。
フラグメントとアクティビティの間でデータを渡す最も賢く試行された方法は、変数を作成することです。例:
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の値を取得できます。幸運を!
私の解決策は、フラグメント内に静的メソッドを記述することです:
public TheFragment setData(TheData data) {
TheFragment tf = new TheFragment();
tf.data = data;
return tf;
}
このようにして、私が必要とするすべてのデータは、フラグメントで動作する必要がある可能性のある他の操作の前に、フラグメント内にあると確信しています。また、私の見た目はすっきりしています。
最新のナビゲーションアーキテクチャコンポーネントを使用しているときに、同様の問題に遭遇しました。私の呼び出しアクティビティからFragmentにバンドルを渡すことで、上記のすべてのコードを試してみました。
Androidの最新の開発トレンドに従う最善の解決策は、View Model(Android Jetpackの一部)を使用することです。
親アクティビティでViewModelクラスを作成して初期化します。このViewModelはアクティビティとフラグメント間で共有する必要があることに注意してください。
次に、フラグメントのonViewCreated()内で、同じViewModelを初期化し、ViewModelフィールドをリッスンするようにオブザーバーをセットアップします。
必要な場合に役立つ、詳細なチュートリアルを以下に示します。
あなたの活動で静的変数を宣言する
public static HashMap<String,ContactsModal> contactItems=new HashMap<String, ContactsModal>();
次に、フラグメントで次のようにします
ActivityName.contactItems.put(Number,contactsModal);