在我的Android应用程序中,我有一个片段活动,它有一个进度条。当任何片段调用接口时,此进度条设置为可见。因此,片段类的代码是这样的:
public class MainScreen extends FragmentActivity {
public interface OnConnectingToInternet {
public void showProgressbar(boolean flag);
}
// rest of codes
.
.
.
// Implementing Interface
public void showProgressbar(boolean flag) {
if(flag){
myProgressbar.showProgressBar();
} else {
myProgressbar.hideProgressBar();
}
}
}
每个片段应该连接到Internet并获取数据,但在此之前它们应该调用接口。我为一个类编写了以下代码(其他片段的代码就是这样)。
public class TopRecipesFragment extends Fragment {
private OnConnectingToInternet onConnectingToInternet;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// onConnectingToInternet = (OnConnectingToInternet) activity;
Log.i(TAG, "Fragment attached to activity.");
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
New MyAsyncTask.execute();
}
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected void onPreExecute() {
Log.i(TAG, "myAsyncTask is about to start...");
onConnectingToInternet.showProgressbar(true);
}
@Override
protected Boolean doInBackground(Void... params) {
...
}
@Override
protected void onPostExecute(Boolean result) {
Log.i(TAG, "myAsyncTask is about to start...");
onConnectingToInternet.showProgressbar(false);
}
}
问题是我不知道如何实例化这个接口。如果我没有放onConnectingToInternet = (OnConnectingToInternet) activity;
,那么在运行应用程序后,它会在NullPointerException
中崩溃。
但是,如果我像这样实例化,那么应用程序因为转换问题而崩溃。我无法以正常方式实例化它,例如onConnectingToInternet = new MainScreen();
。
解决方案是什么?任何建议将不胜感激。感谢
答案 0 :(得分:4)
我会写你正在尝试以下方式:
OnConnectingToInternet.java:
public interface OnConnectingToInternet {
public void showProgressbar(boolean flag);
}
MainScreen.java:
public class MainScreen extends FragmentActivity implements OnConnectingToInternet {
// rest of codes
.
.
.
// Implementing Interface
@Override
public void showProgressbar(boolean flag) {
if(flag){
myProgressbar.showProgressBar();
} else {
myProgressbar.hideProgressBar();
}
}
}
TopRecipesFragment.java:
public class TopRecipesFragment extends Fragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.i(TAG, "Fragment attached to activity.");
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new MyAsyncTask((OnConnectingToInternet)getActivity()).execute();
}
// Make class static to avoid memory leaks
public static class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
// Keep WeakReference to the interface to avoid memory leaks
private final WeakReference<OnConnectingToInternet> connectionRef;
MyAsyncTask(OnConnectingToInternet connection) {
connectionRef = new WeakReference<OnConnectingToInternet>(connection);
}
@Override
protected void onPreExecute() {
Log.i(TAG, "myAsyncTask is about to start...");
OnConnectingToInternet connection = connectionRef.get();
if (null != connection) {
connection.showProgressbar(true);
}
}
@Override
protected Boolean doInBackground(Void... params) {
...
}
@Override
protected void onPostExecute(Boolean result) {
Log.i(TAG, "myAsyncTask is about to start...");
OnConnectingToInternet connection = connectionRef.get();
if (null != connection) {
connection.showProgressbar(false);
}
}
}
答案 1 :(得分:1)
问题在于,有时Fragment的活动时间比其Activity长,例如,如果Activity有配置更改(例如旋转),则Activity被销毁,但Fragment可以保持活动状态,然后重新连接到new(旋转)活动。看这篇文章: Android Fragment lifecycle over orientation changes
因此,使用WeakReference可能会对使用WeakReference的解决方案产生问题,因为在轮换之后,您将获得对旧Activity的引用(或者可能没有)。
虽然我不确定为什么线路在onAttach()上崩溃,但应该没问题。
对我来说似乎有用:
1)当我需要参考Activity时,请调用getActivity()。在onPostExecute()中执行此操作。
2)检查结果是否为空(这可能发生:碎片可以比活动更长寿命)
3)检查activity是否isFinishing() - 您不希望在该状态下执行某些UI事务。
4)将活动投射到您的界面类型。
5)调用showProgressBar()。