ViewPager Активность для уведомления фрагмента о конкретном событии - PullRequest
22 голосов
/ 22 января 2012

У меня есть ViewPager, и он использует FragmentAdapter для отображения нескольких фрагментов одного вида. Хотя эти фрагменты в основном создаются из одного и того же класса, они используют ListView для отображения различной информации. (Очевидно, что ListView накапливается ArrayAdapter.)
Фоновая служба также работает и постоянно получает данные из Интернета. Я хочу иметь возможность обновить конкретный фрагмент в ViewPager, когда моя фоновая служба уведомит меня о конкретном событии.
Как я могу это сделать? Фрагмент кода был бы очень признателен!

(Кстати, я видел этот похожий вопрос , но я понятия не имею, как использовать их предложение!)

Чтобы все было проще: Моя активность с ViewPager:
[Фрагмент 0] [Фрагмент 1] [Фрагмент 2]

Фоновая служба сообщает мне (через трансляцию) обновить ListView в Фрагмент 1 .

EDIT: Вот примеры кодов:

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: Я хотел бы знать, является ли то, что я делаю, правильным способом справиться с тем, что я хочу сделать ... Любое другое решение также приветствуется!

Ответы [ 5 ]

40 голосов
/ 30 января 2012

Попробуйте это,

Зарегистрируйте приемник вещания во всех ваших фрагментах ... вот так

создать класс, который расширяет приемник вещания на все классы, например:

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

и зарегистрируйте этот получатель в onCreate вашего фрагмента ...

например. getActivity().registerReceiver(new FragmentReceiver1(), new IntentFilter("fragmentupdater"));

Теперь назначьте уникальный идентификатор каждому фрагменту, например, 1 для Fragment1, 2 для Fragment2 и аналогично

Теперь, когда вы хотите передать какие-либо данные и обновить какой-либо фрагмент, просто отправьте широковещательную рассылку с данными в намерении и «фрагментом обновления» в качестве фильтра намерения ...

Например:

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 ..., намерение, которое вы получите, является Намерение, которое мы прошли выше

5 голосов
/ 22 января 2012

Вы пробовали 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 в ваш класс фрагмента.Именно вы предложили Fragment1 в качестве имени для простоты.Кроме того, вы не предоставили источник, чтобы помочь нам.Это правда, что вы не можете установить тег Fragment, но почему вы думаете, что можете получить его тег?Обычно Fragment добавляется через FragmentManagers как

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 ) и опубликовать исходный код, чтобы нам не приходилось угадывать, что вам нужно.

2 голосов
/ 16 августа 2015

У меня была такая же проблема, но я исправил ее с помощью 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);

Надеюсь, что это помогает другим.

0 голосов
/ 27 июля 2015

Просто посмотрите на этот ответ https://stackoverflow.com/a/16388650

Он использовал yourAdapter.notifyDataSetChanged(), который является предопределенным методом. Проверьте ссылку, чтобы увидеть, как это делается

Edit: Когда ваш 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 голосов
/ 30 января 2012

Я не знаю достаточно того, что вы делаете, но, похоже, вам нужно использовать шаблон Observer, Callbacks или Listeners.Разве ваш фрагмент не может сделать что-то вроде:

myservice.addMyEventListener(myFragInstance);

, и тогда вы можете быть «уведомлены о конкретном событии».

...