web-dev-qa-db-ja.com

特定のイベントのフラグメントを通知するViewPagerアクティビティ

私はViewPagerを持っていて、同じ種類のいくつかのフラグメントを表示するためにFragmentAdapterを使用しています。これらのフラグメントは基本的に同じクラスからインスタンス化されますが、ListViewを使用して異なる情報を表示しています。 (明らかに、ListViewArrayAdapterによって作成されています。)
バックグラウンドサービスも実行されており、インターネットから常にデータを受信して​​います。バックグラウンドサービスから特定のイベントが通知されたときに、ViewPagerの特定のフラグメントを更新できるようにしたい。
どうやってやるの?コードスニペットをいただければ幸いです。

(ちなみに、私は この同様の質問 を見ましたが、彼らの提案をどのように使用するかわかりません!)

それをすべてもっと簡単にするために:ViewPagerでの私の活動:
[フラグメント0] [フラグメント1] [フラグメント2]

バックグラウンドサービスは、(ブロードキャストを介して)フラグメント1ListViewを更新するように指示します。

編集:サンプルコードは次のとおりです。

public class ChatWindowPager extends FragmentActivity
{
    private ViewPager mViewPager = null;
    private ChatFragmentAdapter mAdapter = null;
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chat_window_pager);

        this.mViewPager = (ViewPager) findViewById(R.id.chatPager);
        this.mAdapter = new ChatFragmentAdapter(getSupportFragmentManager());
        this.mViewPager.setAdapter(this.mAdapter);
        .
        .
        .
    }

    class ChatFragmentAdapter extends FragmentPagerAdapter implements ViewProvider
    {

        public ChatFragmentAdapter(final FragmentManager fm)
        {
            super(fm);
        }

        @Override
        public Fragment getItem(final int arg0)
        {
            String friendId = ..... // Some initializations
            ChatWindowFragment f = ChatWindowFragment.newInstance(friendId);
            return f;
        }

        @Override
        public int getCount()
        {
            ...
        }

        @Override
        public View getView(final int position)
        {
            View v = getLayoutInflater().inflate(R.layout.tab_holder, null);
            .
            .
            .
            return v;
        }
    }
}

これで、フラグメントは次のように定義されます。

public class ChatWindowFragment extends Fragment
{
    public String friendId;
    private ListView lv;

    public static ChatWindowFragment newInstance(final String friendId)
    {
        ChatWindowFragment chatWindowFragment = new ChatWindowFragment();
        Bundle bundle = new Bundle();
        bundle.putString("friendId", friendId);
        chatWindowFragment.setArguments(bundle);
        return chatWindowFragment;
    }

    @Override
    public void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.friendId = getArguments().getString("friendId");
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
    {
        View v = inflater.inflate(R.layout.chat_window, container, false);

        this.friendId = getArguments().getString("friendId");
        .
        .
        .
        return v;
    }

    //The rest of the class

}

FragmentPagerAdapterを使用しているので、各フラグメントのタグを設定する方法がわかりません。 (明らかに、フラグメントを追加するためにトランザクションを使用していません!)

編集2:私がしていることが、私がやりたいことを処理する正しい方法であるかどうかを知りたい...他の解決策大歓迎です!

22
Maghoumi

これを試して、

すべてのフラグメントにブロードキャストレシーバーを登録します...このように

たとえば、次のように、すべてのクラスでブロードキャストレシーバーを拡張するクラスを作成します。

_public class FragmentReceiver1 extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
        }    
}
_

このレシーバーをフラグメントのonCreateに登録します...

例えば。 getActivity().registerReceiver(new FragmentReceiver1(), new IntentFilter("fragmentupdater"));

次に、フラグメント1に1、フラグメント2に2など、各フラグメントに一意のIDを割り当てます。

これで、データを渡し、フラグメントを更新するときはいつでも、インテント内のデータとインテントフィルターとしての「fragmentupdater」を使用してブロードキャストを送信するだけです...

例:

_Intent data = new Intent("fragmentupdater");
data.putString("key","data");
data.putInt("fragmentno",1); // Pass the unique id of fragment we talked abt earlier
activity.sendBroadcast(data);
_

これで、各フラグメントがデータを受信しますが、同じフラグメントのデータがonReceive関数で渡された一意のIDであるかどうかを確認できます...取得するインテントは上で渡した意図

40
King RV

試しましたか FragmentManager.findFragmentByTag()

FragmentManager manager = getSupportedFragmentManager();
//with support package, else
//FragmentManager manager = getFragmentManager()
Fragment fragment = manager.findFragmentByTag("Tag You Created the Fragment");
if (fragment instanceof Fragment1){
    Fragment1 fr = (Fragment1)fragment
    fr.updateData(DATA)
    //or any method of your choice
} 

編集:私は注意深く読んだ! instanceOfは、FragmentをFragmentクラスにキャストします。シンプルさの名前としてFragment1を提案したのはあなたでした。また、あなたは私たちを助けるための情報源を提供しませんでした。確かに、Fragmentのタグを設定することはできませんが、なぜそのタグを取得できると思いますか?通常、FragmentFragmentManagersを介して追加されます。

FragmentManager manager = getSupportedFragmnentManager()
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(int containerViewId, Fragment fragment, String tag);
// or transaction.add(Fragment fragment, String tag)
// ...other transactions
transaction.commit()

EDIT2:それはとても簡単です。あなたのコードによると、あなたはただ呼び出すことができます

Fragment fragment = mAdapter.getItem(0) // 0||1||2

ドキュメントを読んで(つまり、 FragmenPagerAdapter について)、ソースコードを投稿することを検討してください。そうすれば、必要なものを推測する必要がなくなります。

5
Rafael T

私は同じ問題を抱えていましたが、次のようにlocalBroadcastReceiverで修正しました:

アクティビティにレシーバーを作成して登録します:

 /**
 * ******************************
 * Receiver to process the message
 * *******************************
 */
private BroadcastReceiver onNotice = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //You can send any extra data if you need like this
        final int type = intent.getIntExtra("fragment.data", -1);
        Log.d(tag, "main class: " + type);
        //also refresh your fragment like this
        mViewPager.getViewPager().getAdapter().notifyDataSetChanged();
    }
};    

@Override
protected void onResume() {
    super.onResume();

    //Register a localbroadCast with the your filter
    IntentFilter thinaireFilter = new IntentFilter("your.filter");
    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, thinaireFilter);
}

LocalBroadCastを削除することを忘れないでください

//remove the LocalBroadCast when no need it
@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}

アダプタやサービスなどが必要な場所からブロードキャストを送信します

Intent sendBroadCastData = new Intent("your.filter");
sendBroadCastData.putExtra("fragment.data", myData);
LocalBroadcastManager.getInstance(context).sendBroadcast(sendBroadCastData);

それが他の人に役立つことを願っています。

2
Rensodarwin

あなたが何をしているのかよくわかりませんが、オブザーバーパターン、コールバック、またはリスナーを使用する必要があるようです。あなたのフラグメントはただ次のようなことをすることはできません:

myservice.addMyEventListener(myFragInstance);

そうすれば、「特定のイベントを通知」することができます。

0
user123321

この答えを見てください https://stackoverflow.com/a/1638865

彼は、事前定義されたメソッドであるyourAdapter.notifyDataSetChanged()を使用しました。リンクをチェックして、その方法を確認してください

編集:AsyncTaskが完了したら、次のようなonPostExecuteメソッドを実行する必要があります。

ResultFragment resultFrag = (ResultFragment) getSupportFragmentManager()
                                 .findFragmentByTag("FragToRefresh");
if (resultFrag != null) {
    resultFrag.refreshData(refreshedArray);
}

そして、ResultFragmentには、refreshDataメソッドが必要です。これは次のようなものです。

public void refreshData(ArrayList<YourObject> data) {
   yourArray = new ArrayList<YourObject>(data);
   yourAdapter.notifyDataSetChanged();
}
0
Gaurav Dwivedi

すべてをシンプルにするためにイベントバスを使用する必要がありました https://github.com/greenrobot/EventBus

0