在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(Context context)中进行相同的检查是否安全,或者是否有更好的方法来获取持有者活动实例?
答案 0 :(得分:27)
检查源代码:
cmake/
如果有主机活动,则/**
* 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)
。
答案 1 :(得分:4)
嗯,弃用的是onAttach(Activity activity);
方法,但整个流程仍然存在。所以你可能没有做任何事情,因为onAttach(Activity activity);
将会得到足够长时间的支持。
答案 2 :(得分: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);
}
}
备注强>
由于父Activity必须实现我们的OnFragmentInteractionListener
(任意命名的接口),因此检查(context instanceof OnFragmentInteractionListener)
可确保上下文实际上是活动。
请注意,我们正在使用支持库。否则,API 23的早期版本将不会调用onAttach(Context context)
。
另见
答案 3 :(得分: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
进行类型转换以获取活动。这是因为Context可以传播到作为活动的子类。
另一个问题,API 23离现在还很遥远,让我们担心。如果你担心,使用build pragma(静态Build)可能是个不错的选择。
答案 4 :(得分:1)
我遇到了同样的情况。我已经经历了各种帖子,最后在片段的onCreate()块中实现了我的代码。到现在我还没有遇到任何问题,我认为它不会成为一个问题,因为在onAttach之后立即调用onCreate的生命周期。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
listnener = (TilesOnClickListnener)getActivity();
} catch (ClassCastException e) {
throw new ClassCastException(getActivity().toString() + " must implement OnArticleSelectedListener");
}
}
答案 5 :(得分:1)
我使用原生Fragment
而不是one from the Support Library。我在我的代码中放了两个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)
方法中。
答案 6 :(得分:0)
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);
}
}