从AsyncTaskLoader onLoadFinished后动态更新片段的UI - 无法获取ViewGroup

问题描述:

以前,我有一个Fragment,它根据耗时的提取数据更新其UI。从AsyncTaskLoader onLoadFinished后动态更新片段的UI - 无法获取ViewGroup

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

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

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

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

我所知道的是动态更新分段UI,onLoadFinishedAsyncTaskLoader后正确的方法是什么?

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

使用Loader不要求你必须使用一个ListView,你可以更新你的应用程序的目标是无论大家认为。

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

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

谢谢。在从'onCreateView'返回之前,我可以确认从R.layout.home_menu膨胀的View是一个ScrollView(正确,因为home_menu XML的根是ScrollView)。然而,当我在onLoadFinished中调用getView时,我得到了'android.support.v4.app.NoSaveStateFrameLayout'。我可以知道什么是我得到ScrollView的正确方法吗? – 2013-03-20 07:38:43

+0

@CheokYanCheng你不要简单地使用'getView()'。你为要放置视图的ViewGroup分配一个id(我使用了'R.id.containerId'),并且寻找该视图(在getView()')上使用'findViewById()'来添加额外的意见。 – Luksprog 2013-03-20 07:42:12

+0

好的。感谢这项技术。我以为我需要在'onLoadFinished'内提供容器及其所有UI元素。实际上,我可以在'onCreateView'中提供容器,然后通过'onLoadFinished'添加新的UI元素 – 2013-03-20 12:16:32

有一段时间我也试图达到同样的效果。基于以上的答案,什么工作对我来说是这样的:

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

我的布局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已更改。

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