OnAttach (Activity) устарел: где я могу проверить, реализует ли эта функция интерфейс обратного вызова
До API 23 я использовал методы Fragment onAttach для получения моего экземпляра слушателя, затем ссылка очищается внутри onDetach. например:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mListener = null;
try {
mListener = (SellFragmentListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement SellFragmentListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
Безопасно ли выполнять одну и ту же проверку внутри onAttach (контекст контекста) или есть лучший способ получить экземпляр активности владельца?
Ответы
Ответ 1
Проверьте исходный код:
/**
* Called when a fragment is first attached to its context.
* {@link #onCreate(Bundle)} will be called after this.
*/
public void onAttach(Context context) {
mCalled = true;
final Activity hostActivity = mHost == null ? null : mHost.getActivity();
if (hostActivity != null) {
mCalled = false;
onAttach(hostActivity);
}
}
/**
* @deprecated Use {@link #onAttach(Context)} instead.
*/
@Deprecated
public void onAttach(Activity activity) {
mCalled = true;
}
Итак, onAttach(Activity activity)
вызывается onAttach(Context context)
, если есть активность хоста. Вы можете безопасно использовать onAttach(Activity activity)
.
Ответ 2
Ну, то, что устарело, - это метод onAttach(Activity activity);
, но весь поток остается. поэтому вы можете ничего не делать, поскольку onAttach(Activity activity);
будет поддерживаться достаточно долго.
Ответ 3
Мне никогда не приходилось использовать onAttach(Context context)
, но я думаю, что ваш код в основном хорош. Итак, вот мое предложение, используя ваш код:
public void onAttach (Context context) {
super.onAttach(context);
try {
Activity activity = (Activity) context;
mListener = (SellFragmentListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement SellFragmentListener");
}
}
Основное отличие состоит в том, что я могу придать тип context
для получения Activity. Это связано с тем, что Контекст может распространяться в подкласс, который является активностью.
Еще одна проблема, API 23 все еще далека от нас, чтобы мы могли волноваться. Если вы беспокоитесь, использование build pragma (static Build) может быть хорошим вариантом.
Ответ 4
Как показано в ответе Zsolt Mester, onAttach(Activity activity)
устарел в пользу onAttach(Context context)
. Таким образом, все, что вам нужно сделать, это проверить, чтобы контекст был активным.
В Android Studio, если вы перейдете к Файл > Создать > Фрагмент, вы можете получить автоматически сгенерированный код, который будет содержать правильный синтаксис.
import android.support.v4.app.Fragment;
...
public class MyFragment extends Fragment {
private OnFragmentInteractionListener mListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate fragment layout
return inflater.inflate(R.layout.fragment_myfragment, container, false);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
Примечания
-
Поскольку родительская активность должна реализовать наш OnFragmentInteractionListener
(интерфейс с произвольным именем), проверка (context instanceof OnFragmentInteractionListener)
гарантирует, что контекст является фактически активностью.
-
Обратите внимание, что мы используем библиотеку поддержки. В противном случае onAttach(Context context)
не будет вызываться в версиях Android до версии API 23.
См. также
Ответ 5
Я столкнулся с такой же ситуацией. Я прошел через различные должности и, наконец, реализовал свой код в блоке onCreate() фрагмента. До сих пор я не сталкивался с какой-либо проблемой, и я думаю, что это не будет проблемой, поскольку onCreate вызывается сразу после onAttach в жизненном цикле.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
listnener = (TilesOnClickListnener)getActivity();
} catch (ClassCastException e) {
throw new ClassCastException(getActivity().toString() + " must implement OnArticleSelectedListener");
}
}
Ответ 6
public class MainActivity extends AppCompatActivity implements topsection.TopSectionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void createMeme(String top, String bottom){
bottomsection fragmentbottom = (bottomsection) getSupportFragmentManager().findFragmentById(R.id.fragment2);
fragmentbottom.setMemeText(top, bottom);
}
}
Ответ 7
Я использую собственный Fragment
, а не one из Библиотеки поддержки. Я поместил оба метода onAttach()
в свой код и проделал некоторую отладку на устройствах с разными версиями SDK. Я обнаружил, что:
SDK 22 и ниже - вызывается только onAttach(Activity)
. Не удивительно, потому что onAttach(Context)
был введен только в SDK 23.
SDK 23 и выше - onAttach(Context)
вызывается первым, а затем onAttach(Activity)
. (Это согласуется с тем, что @Zsolt Mester сказал об исходном коде в другом ответе на этот пост.)
Так как minSdkVersion
для моего приложения было ниже 23, я просто решил полностью опустить onAttach(Context)
и просто добавить аннотацию @SuppressWarnings("deprecation")
к существующему методу onAttach(Activity)
.