it-swarm.com.ru

Общение между фрагментом и действием - лучшие практики

Этот вопрос в основном для того, чтобы узнать мнение о том, как лучше всего справиться с моим приложением. У меня есть три фрагмента, которые обрабатываются одним действием. Фрагмент А имеет один интерактивный элемент - фотографию, а Фрагмент Б - 4 интерактивных элемента - кнопки. Другой фрагмент просто отображает детали при нажатии на фотографию. Я использую ActionBarSherlock. 

Screen shot

Кнопки «Вперед» и «Назад» должны изменить фотографию на следующую или предыдущую позу соответственно. Я мог сохранить фотографию и кнопки в одном фрагменте, но хотел, чтобы они были разделены на случай, если я захочу переставить их в планшете. 

Мне нужен совет - мне объединить фрагменты A и B? Если нет, мне нужно будет выяснить, как реализовать интерфейс для трех интерактивных элементов. 

Я подумал об использовании Roboguice, но я уже расширяю использование SherlockFragmentActivity, так что не стоит. Я видел упоминание об Отто, но я не видел хороших учебников о том, как включить в проект. Как вы думаете, какой должна быть лучшая практика дизайна? 

Мне также нужна помощь в выяснении того, как общаться между фрагментом и действием. Я хотел бы, чтобы некоторые данные были «глобальными» в приложении, например идентификатор позы. Есть ли какой-нибудь пример кода, который я могу увидеть, кроме информации разработчика Android? Это не все, что полезно. 

Кстати, я уже храню всю информацию о каждой позе в базе данных SQLite. Это легкая часть. 

49
Kristy Welsh

Самый простой способ связи между вашей деятельностью и фрагментами - это использование интерфейсов. Идея в основном состоит в том, чтобы определить интерфейс внутри данного фрагмента A и позволить деятельности реализовать этот интерфейс.

Как только он реализовал этот интерфейс, вы можете делать все, что захотите, в методе, который он переопределяет.

Другая важная часть интерфейса - вы должны вызывать абстрактный метод из вашего фрагмента и не забывать приводить его к своей деятельности. Он должен перехватить ClassCastException, если не все сделано правильно.

На Simple Blog Blog есть хорошее руководство о том, как делать именно такие вещи.

Я надеюсь, что это было полезно для вас!

70
Eenvincible

Предлагаемый метод связи между фрагментами - использовать обратные вызовы\слушатели, которыми управляет ваша основная активность.

Я думаю, что код на этой странице довольно ясен: http://developer.Android.com/training/basics/fragments/communicating.html

Вы также можете сослаться на приложение IO Расписание 2012 года, которое разработано, чтобы быть де-факто справочным приложением. Его можно найти здесь: http://code.google.com/p/iosched/

Кроме того, вот вопрос SO с хорошей информацией: Как передавать данные между фрагментами

23
Booger

Это реализуется интерфейсом обратного вызова: Прежде всего мы должны сделать интерфейс:

public interface UpdateFrag {
     public void updatefrag();
    }

В действии сделайте следующий код:

UpdateFrag updatfrag ;
public void updateApi(UpdateFrag listener) {
        updatfrag = listener;
   }

из события, из-за которого обратный вызов должен срабатывать в действии:

updatfrag.updatefrag();

Во Fragment реализуем интерфейс, в CreateView делаем следующий код:

 ((Home)getActivity()).updateApi(new UpdateFrag() {
                @Override
                public void updatefrag() {
                   .....your stuff......
                }
            });
9
Jyoti

Я создал библиотеку аннотаций, которая может помочь вам. проверить это . https://github.com/zeroarst/callbackfragment/

@CallbackFragment
public class MyFragment extends Fragment {

    @Callback
    interface FragmentCallback {
       void onClickButton(MyFragment fragment);
    }    
    private FragmentCallback mCallback;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt1
                mCallback.onClickButton(this);
                break;
            case R.id.bt2
                // Because we give mandatory = false so this might be null if not implemented by the Host.
                if (mCallbackNotForce != null)
                mCallbackNotForce.onClickButton(this);
                break;
        }
    }
}

Затем он генерирует подкласс вашего фрагмента. И просто добавьте его в FragmentManager.

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction()
            .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM")
            .commit();
    }

    Toast mToast;

    @Override
    public void onClickButton(MyFragment fragment) {
        if (mToast != null)
            mToast.cancel();
        mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT);
        mToast.show();
    }
}
4
Arst

Существует несколько способов взаимодействия между действиями, фрагментами, сервисами и т.д. Очевидным является взаимодействие с использованием интерфейсов. Однако это не продуктивный способ общения. Вы должны реализовать слушателей и т.д.

Мое предложение состоит в том, чтобы использовать шину событий. Шина событий является реализацией шаблона публикации/подписки.

Вы можете подписаться на события в своей деятельности, а затем можете публиковать эти события в своих фрагментах и ​​т.д.

Здесь в моем блоге вы можете найти более подробную информацию об этом шаблоне, а также пример проекта , чтобы показать использование.

2
Gunhan

Я не уверен, что действительно понял, что вы хотите сделать, но предлагаемый способ взаимодействия между фрагментами - это использование обратных вызовов с Activity, а не непосредственно между фрагментами. Смотрите здесь http://developer.Android.com/training/basics/fragments/communicating.html

1
alex

Для связи между Activity и Fragments есть несколько вариантов, но после большого чтения и опыта я обнаружил, что это можно возобновить следующим образом:

  • Activity хочет общаться с дочерним элементом Fragment => Просто напишите открытые методы в своем классе Fragment и позвольте Activity вызывать их
  • Fragment хочет связаться с родителем Activity => Это требует немного больше работы, так как официальная ссылка Android https://developer.Android.com/training/basics/fragments/communicating предполагает, что это будет отличная идея определить interface, который будет реализован Activity и который установит контракт для любой Activity, которая хочет связаться с этой Fragment. Например, если у вас есть FragmentA, который хочет обмениваться данными с любым activity, который включает его, то определите FragmentAInterface, который определит, какой метод может вызывать FragmentA для activities, решившего его использовать.
  • Fragment хочет общаться с другими Fragment => Это тот случай, когда вы получаете самую «сложную» ситуацию. Поскольку вам может понадобиться передать данные из FragmentA во FragmentB и наоборот, это может привести к определению 2 интерфейсов, FragmentAInterface, который будет реализован с помощью FragmentB и FragmentAInterface, который будет реализован с помощью FragmentA. Это начнет портить вещи. И представьте, если у вас есть еще несколько Fragments, и даже родитель activity хочет с ними связаться. Что ж, этот случай - идеальный момент для установки общей ViewModel для activity, и это fragments. Более подробная информация здесь https://developer.Android.com/topic/libraries/architecture/viewmodel . По сути, вам нужно определить класс SharedViewModel, который содержит все данные, которые вы хотите разделить между activity и fragments, которые будут нуждаться в передаче данных между ними.

Случай ViewModel, в конце концов, значительно упрощает задачу, так как вам не нужно добавлять дополнительную логику, которая делает вещи грязными в коде и грязными. Кроме того, это позволит вам отделить сбор (посредством обращений к базе данных SQLite или API) данных от Controller (activities и fragments).

1

Вы можете создать объявление открытого интерфейса с объявлением функции во фрагменте и реализовать интерфейс в действии. Затем вы можете вызвать функцию из фрагмента. 

0
Jacob Abraham

Я использую Intents, чтобы сообщать о действиях обратно к основному виду деятельности. Основным действием является их прослушивание путем переопределения onNewIntent (намерение намерения). Основная деятельность переводит эти действия, например, в соответствующие фрагменты.

Так что вы можете сделать что-то вроде этого:

public class MainActivity extends Activity  {

    public static final String INTENT_ACTION_SHOW_FOO = "show_foo";
    public static final String INTENT_ACTION_SHOW_BAR = "show_bar";


   @Override
   protected void onNewIntent(Intent intent) {
        routeIntent(intent);
   }

  private void routeIntent(Intent intent) {
       String action = intent.getAction();
       if (action != null) {               
            switch (action) {
            case INTENT_ACTION_SHOW_FOO:
                // for example show the corresponding fragment
                loadFragment(FooFragment);
                break;
            case INTENT_ACTION_SHOW_BAR:
                loadFragment(BarFragment);
                break;               
        }
    }
}

Затем внутри любого фрагмента, чтобы показать фрагмент foo:

Intent intent = new Intent(context, MainActivity.class);
intent.setAction(INTENT_ACTION_SHOW_FOO);
// Prevent activity to be re-instantiated if it is already running.
// Instead, the onNewEvent() is triggered
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
getContext().startActivity(intent);
0
Pepster