【问题标题】:Update the Fragment's UI dynamically after onLoadFinished from AsyncTaskLoader - Not able to obtain ViewGroup从 AsyncTaskLoader onLoadFinished 后动态更新 Fragment 的 UI - 无法获取 ViewGroup
【发布时间】:2014-10-11 23:23:03
【问题描述】:

以前,我有一个 Fragment,它会根据耗时的获取数据更新其 UI。

public class HomeMenuFragment extends SherlockFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Infos arg1 = performTimeConsumingDataStructureLoading();

        // Add in various UI views in v, according to information in loaded
        // data structure.
        View v = inflater.inflate(R.layout.home_menu, container, false);
        // ...
        // Adding several LinearLayout and TextView into v, based on
        // information from loaded data structure (arg1)
        // ...
        return v;
    }
    ....
}

这真的不是一个好的设计。因为有时performTimeConsumingDataStructureLoading 可能需要超过 5 秒,我会得到 ANR(应用程序无响应)

通过引用http://developer.android.com/reference/android/content/AsyncTaskLoader.html,我最终得到了更好的解决方案。我遇到的例子是,它通过ArrayAdapter间接更新它的UI。

public class HomeMenuFragment extends SherlockFragment implements LoaderManager.LoaderCallbacks<HomeMenuFragment.Infos> {
    @Override
    public void onLoadFinished(Loader<Infos> arg0, Infos arg1) {
        LayoutInflater inflater = this.getLayoutInflater(null);
        ViewGroup container = (ViewGroup)this.getView().getParent();
        // Remove previous old views, as onLoadFinished might be triggered
        // by onContentChanged too.
        container.removeAllViews();

        View v = inflater.inflate(R.layout.home_menu, container, false);
        // ...
        // Adding several LinearLayout and TextView into v, based on
        // information from loaded data structure (arg1)
        // ...
        container.addView(v);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }     
    ....
}

我没有ArrayAdapter,因为我没有使用ListFragment。我想要做的是将几个TextView 添加到几个LinearLayout 中。然后,我将LinearLayout添加到Fragment的容器中。

但是,下面的代码给了我空指针异常。

ViewGroup container = (ViewGroup)this.getView().getParent();

我知道在 onLoadFinishedAsyncTaskLoader 之后动态更新 Fragment UI 的正确方法是什么?

【问题讨论】:

    标签: android android-layout android-fragments


    【解决方案1】:

    然而,我遇到的大多数例子是,他们间接更新了他们的 UI 通过 ArrayAdapter。

    使用Loader 并不要求您必须使用ListView,您可以更新您在应用程序中定位的任何视图。

    我知道动态更新 Fragment UI 的正确方法是什么, 在 AsyncTaskLoader 的 onLoadFinished 之后?

    Fragment 的视图中获取对容器的引用,您将在其中放置额外视图并添加新视图。

    @Override
    public void onLoadFinished(Loader<Infos> arg0, Infos arg1) {      
        // for some reason the fragment's view isn't built yet so abort things 
        if (getView() == null) {
             ViewGroup container = (ViewGroup) getView().findViewById(R.id.containerId);
             ViewGroup container = getViewcontainer.removeAllViews();
             // ...
             // Adding several LinearLayout and TextView into v, based on
             // information from loaded data structure (arg1)
             // ...
             container.addView(v);
        }
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.home_menu, container, false);;
    }    
    

    【讨论】:

    • 谢谢。在从onCreateView 返回之前,我可以确认从 R.layout.home_menu 膨胀的 View 是一个 ScrollView(正确。因为 home_menu XML 的根是 ScrollView)。但是,当我在 onLoadFinished 中调用 getView 时,我得到了android.support.v4.app.NoSaveStateFrameLayout。我可以知道获取 ScrollView 的正确方法是什么吗?
    • @CheokYanCheng 你不要简单地使用getView()。您为要放置视图的ViewGroup 分配一个ID(我使用了R.id.containerId),然后查找该视图(在getView() 上使用findViewById())以添加额外的视图。
    • 好的。感谢您的技术。我认为我需要在onLoadFinished 中提供容器及其所有 UI 元素。其实我可以在onCreateView中提供容器,然后通过onLoadFinished添加新的UI元素
    【解决方案2】:

    有一段时间我也在努力实现同样的目标。根据上述答案,对我有用的是:

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        adapter.swapCursor(cursor);
    
        ViewGroup container = (ViewGroup) getView().findViewById(R.id.fragment_oam);
    
        if (container != null) {
            if (adapter.getCount() == 0) {
                Log.v(TAG, "Count is: " + adapter.getCount());
                container.setBackgroundColor(Color.BLUE);
            } else {
                Log.v(TAG, "Count is: " + adapter.getCount());
                container.setBackgroundColor(Color.WHITE);
            }   
        } else {
            Log.v(TAG, "Container is null");
        }
    }
    

    而我的 Layout xml 如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/background"
        android:background="#FFF">    
    <fragment
        android:name="com.myapp.OAMCursorLoader"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fragment_oam">
    </fragment>
    

    现在,当 ContentResolver 更新光标时,onLoadFinished 会根据可见屏幕的背景检查光标是否为空或是否包含某些内容,即 ListFragment 已更改。

    您可以使用背景设置,使用可绘制的图像而不是颜色,这取决于您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多