【问题标题】:Wait until fragment has been added to the UI等到片段被添加到 UI
【发布时间】:2015-02-11 14:39:32
【问题描述】:

在我的应用程序中,我需要在横向模式下附加两个片段。为了做到这一点,第二个片段需要等到第一个片段被附加(添加)后,才能被添加。原因是第一个片段需要执行第二个片段需要的功能。我设法通过一个线程做到了这一点,但在这种情况下,它只等待指定的时间量,然后再附加第二个片段,如果第一个片段没有在给定的时间内附加,应用程序将崩溃,因为第二个片段片段没有必要的数据。

下面的代码有什么更好的做法(示例)(比如等到第一个片段被附加,并且在某个时间间隔内没有)? :

getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.mainContent, fragment).commit();
        Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    synchronized (this) {
                        wait(1000);
                    }
                } catch (InterruptedException e) {

                }
                if (isLandscape) {
                openSecondFragment(mIndex, R.id.rightConent);
                }
            }
        };
        thread.start();

非常感谢。

第一个片段中需要执行的处理程序:

@SuppressLint("HandlerLeak")
protected void loadAccountList() {

    LoadAccountList loadAccountListThread = new LoadAccountList(new Handler() {

        @SuppressWarnings("unchecked")
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case LOAD_SUCCESSFUL_CODE:
                items = (ArrayList<Account>) msg.obj;
                break;
            case LOAD_FAILED_IOEXCEPTION_CODE:
                getActivity().showDialog(ERROR_DIALOG);
                break;
            default:
                break;
            }
        }
    });
    loadAccountListThread.start();

【问题讨论】:

    标签: android multithreading android-fragments


    【解决方案1】:

    片段生命周期在这里对您有利。根据文档,方法 onStart() 是“当片段对用户可见时调用”,所以我建议你在你的第一个片段类中做这样的事情:

    public void onStart() {
    
        super.onStart();
        ((MainActivity)getActivity()).loadSecondFragment();
    }
    

    在你的活动中:

    public void loadSecondFragment() {
        if (isLandscape) {
            openSecondFragment(mIndex, R.id.rightConent);
        }    
    }
    

    瞧!尝试任何一种生命周期方法,看看哪种方法最适合您的目的。

    【讨论】:

    • 感谢您的回答。我试过你的建议,但结果是一样的。第二个片段添加得太快,因此应用程序崩溃,因为它没有来自第一个片段的必要数据。
    • 只说一句,在你执行完你的函数后调用((MainActivity)getActivity()).loadSecondFragment();。不仅仅是在某些生命周期方法中随机出现。
    • @SnyersK 所说的非常重要,您在第一个片段中在哪里调用该必要功能?
    • 更具体地说,第一个片段包含一个询问服务器的线程,我需要来自第二个片段的服务器的信息。
    • 好的,等到服务器响应,然后你调用((MainActivity)getActivity()).loadSecondFragment(); 就可以了
    【解决方案2】:

    您可以通过注册FragmentLifecycleCallbacks来观察片段的创建 在FragmentManager

    实现您感兴趣的回调,例如onFragmentAttachedonFragmentResumed

    【讨论】:

      【解决方案3】:

      在创建 Fragment 时调用 onCreateView

      public static class CustomFragment extends SupportMapFragment{
      
              public CustomFragment() {}
      
              @Override
              public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) {
                  return super.onCreateView(arg0, arg1, arg2);
      
              }
      }
      

      【讨论】:

      • 是的,但我需要以某种方式从活动中访问它。我尝试了类似:fragment.isAdded() 而不是线程,但在这种情况下,它每次都返回 null。
      • 您可能想等到onAttach。然后查看developer.android.com/training/basics/fragments/… 了解如何通知活动片段已准备好
      • 好,在构造函数中添加监听,在onCreateView中调用
      【解决方案4】:

      首先@SuppressLint("HandlerLeak") 不好。如果你不小心泄漏,你的内存就会被填满。

      我的解决方案(这是个人喜好)

      我喜欢使用 Otto 在保持松耦合的同时传递消息。 它允许您设置一个 EventBus,不同的类可以简单地注册并接收他们想要的事件。 在这种情况下,您可以创建一个辅助类来加载数据并在收到数据(或错误)时触发事件。 然后你在你的第二个片段中捕捉到它并填充你的列表。 (同时你可以显示一个不定的进度条什么的)

      这样,您在加载片段之前不必等待接收到数据。

      您可以在此处找到文档:https://github.com/square/otto

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-14
        • 1970-01-01
        • 1970-01-01
        • 2016-07-29
        相关资源
        最近更新 更多