【问题标题】:How to instantiate interface in fragment?如何在片段中实例化接口?
【发布时间】:2012-07-22 08:01:35
【问题描述】:

在我的 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();
        }
    }

}

每个片段都应该连接到互联网并获取数据,但在此之前它们应该调用接口。我为一个类编写了以下代码(其他片段的代码是这样的)。

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();

解决办法是什么?任何建议将不胜感激。谢谢

【问题讨论】:

    标签: android interface fragment instantiation


    【解决方案1】:

    我会写你正在尝试执行以下方式:

    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);
                }
           }
    } 
    

    【讨论】:

    • 哇,谢谢sandrstar。正是我正在寻找的东西。只是一个问题,我可以将大部分在 MyAsyncTask 类中编写的代码重新定位到 onActivityCreated() 方法吗?我想总结一下。谢谢
    • 这是可能的,但是您可能需要使 MyAsyncTask 不是静态的,这不太好。
    【解决方案2】:

    问题在于,有时 Fragment 的寿命比它的 Activity 长,例如,如果 Activity 有配置更改(例如旋转),则 Activity 被销毁,但 Fragment 可以保持活动状态,然后重新附加到新的 (旋转)活动。看到这个帖子: Android Fragment lifecycle over orientation changes

    因此,您可能对使用 Wea​​kReference 提出的解决方案有疑问,因为在轮换之后,您将获得对旧 Activity 的引用(或者可能什么也没有)。

    虽然我不确定为什么线路在 onAttach() 中崩溃,但应该没问题。

    什么似乎对我有用:

    1) 当我需要 Activity 的引用时,调用 getActivity()。在 onPostExecute() 中执行此操作。

    2) 检查结果是否为 null(可能会发生这种情况:片段的寿命可能比它们的活动长)

    3) 检查活动是否为 isFinishing() - 您不想在该状态下执行某些 UI 操作。

    4) 将活动投射到您的界面类型。

    5) 调用 showProgressBar()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2016-10-04
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多