Android 更新片段';从AsyncTaskLoader加载完成后动态加载UI-无法获取视图组

Android 更新片段';从AsyncTaskLoader加载完成后动态加载UI-无法获取视图组,android,android-layout,android-fragments,Android,Android Layout,Android Fragments,以前,我有一个片段,它根据耗时的获取数据更新其UI public class HomeMenuFragment extends SherlockFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Infos arg1 = performTimeConsu

以前,我有一个
片段
,它根据耗时的获取数据更新其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;
    }
    ....
}
这真的不是一个好的设计。有时,
执行TimeConsumingDatastructureLoading
可能需要5秒以上的时间,我会得到ANR(应用程序没有响应)

通过引用,我最终得到了更好的解决方案。我遇到的例子是,它通过
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);
    }     
    ....
}
AsyncTaskLoader
中的
onLoadFinished
之后,我知道动态更新片段UI的正确方法是什么

然而,我遇到的大多数例子是,他们间接地更新他们的UI 通过阵列适配器

使用
加载程序
不需要使用
列表视图
,您可以更新应用程序中的任何目标视图

我知道动态更新片段UI的正确方法是什么, 从AsyncTaskLoader加载完成后

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

@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);;
}    
@覆盖
public void onLoadFinished(加载程序arg0,信息arg1){
//由于某些原因,片段的视图尚未构建,因此中止操作
如果(getView()==null){
ViewGroup容器=(ViewGroup)getView().findViewById(R.id.containerId);
ViewGroup container=getViewcontainer.removeAllViews();
// ...
//基于将多个LinearLayout和TextView添加到v中
//来自已加载数据结构(arg1)的信息
// ...
container.addView(v);
}
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
返回充气机。充气(R.layout.home_菜单,容器,错误);;
}    

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

@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");
    }
}
@覆盖
public void onLoadFinished(加载器,光标){
适配器.swapCursor(游标);
ViewGroup容器=(ViewGroup)getView().findViewById(R.id.fragment\u oam);
if(容器!=null){
if(adapter.getCount()==0){
Log.v(标记“Count is:”+adapter.getCount());
容器.立根基色(颜色.蓝色);
}否则{
Log.v(标记“Count is:”+adapter.getCount());
容器.立根基色(颜色.白色);
}   
}否则{
Log.v(标记“容器为空”);
}
}
我的布局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是否已更改


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

谢谢。在从
onCreateView
返回之前,我可以确认从R.layout.home\u菜单膨胀的视图是一个ScrollView(正确。因为home\u菜单XML的根是ScrollView)。然而,当我在onLoadFinished中调用getView时,我得到的是
android.support.v4.app.NoSaveStateFrameLayout
。我可以知道什么是获取ScrollView的正确方法吗?@CheokYanCheng您不只是使用
getView()
。将id分配给要放置视图的
视图组
(我使用了
R.id.containerId
),然后查找该视图(使用
getView()
上的
findViewById()
)以添加额外视图。确定。谢谢你的技术。我想我需要在
onLoadFinished
中提供容器及其所有UI元素。事实上,我可以在
onCreateView
中提供容器,然后通过
onLoadFinished
添加新的UI元素
<?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>