带有自定义 CursorAdapter 的 Android ListFragment 不显示数据

Posted

技术标签:

【中文标题】带有自定义 CursorAdapter 的 Android ListFragment 不显示数据【英文标题】:Android ListFragment with custom CursorAdapter not showing data 【发布时间】:2015-04-29 05:38:39 【问题描述】:

所以基本上我有一个这样的 ListFragment 设置

public class ObavijestiFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> 
private View mApiError;
private ObavijestiAdapter mAdapter;
private static String TAG="ObavijestiFragment";

public static ObavijestiFragment newInstance() 
    return new ObavijestiFragment();


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    View v = inflater.inflate(R.layout.fragment_obavijesti, container, false);
    return v;


@Override
public void onViewCreated(View view, Bundle savedInstanceState) 
    mApiError = view.findViewById(R.id.api_error);

另外,我像这样实现了onActivityCreatedonLoadFinished

public void onActivityCreated(Bundle savedInstanceState) 
    super.onActivityCreated(savedInstanceState);
    Activity activity = getActivity();

    if (!activity.isFinishing()) 
        Loader loader = getActivity().getSupportLoaderManager().getLoader(Config.OBAVIJESTI_CURSOR_ID);

        mAdapter = new ObavijestiAdapter(activity, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

        setListAdapter(mAdapter);

        if (loader != null && !loader.isReset()) 
            getActivity().getSupportLoaderManager().restartLoader(Config.OBAVIJESTI_CURSOR_ID, null, this);
         else 
            getActivity().getSupportLoaderManager().initLoader(Config.OBAVIJESTI_CURSOR_ID, null, this);
        
    


 public void onLoadFinished(Loader<Cursor> loader,Cursor cursor) 
    if(mAdapter!=null && cursor!=null)
        mAdapter.swapCursor(cursor);

我在 onLoadFinished 中的光标有 4 行数据,但我的 ListView 中没有显示这些行。有人可以帮我吗?在我的扩展 CursorAdapter 的自定义适配器中,bindViewnewView 也是较新的。下面是这个适配器。

public class ObavijestiAdapter extends CursorAdapter 
private Cursor mCursor;
private Context mContext;
private final LayoutInflater mInflater;

static class ViewHolder 
    public TextView hTextNaslov;
    public TextView hTextOpis;
    public ImageView hImage;

public ObavijestiAdapter(Context context, Cursor c, int flags) 
    super(context, c, flags);
    mInflater = LayoutInflater.from(context);
    mContext = context;


@Override
public void bindView(View view, Context context, Cursor cursor) 
    final ViewHolder holder = (ViewHolder)view.getTag();

    //TODO: REMOVE AFTER IMPLEMENTING REAL IMAGE
    int w = 24, h = 24;
    Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
    Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
    //END REMOVE

    holder.hImage.setImageBitmap(bmp);
    holder.hTextNaslov.setText(cursor.getString(cursor.getColumnIndex(DataContract.Obavijesti.OBAVIJESTI_NASLOV)));
    holder.hTextOpis.setText(cursor.getString(cursor.getColumnIndex(DataContract.Obavijesti.OBAVIJESTI_OPIS)));



@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) 
    View view=mInflater.inflate(R.layout.fragment_obavijesti_row,parent,false);

    final ViewHolder holder = new ViewHolder();
    holder.hTextOpis = (TextView) view.findViewById(R.id.obOpis);
    holder.hTextNaslov = (TextView) view.findViewById(R.id.obNaslov);
    holder.hImage = (ImageView) view.findViewById(R.id.oblist_image);
    view.setTag(holder);
    return view;

更新: 我尝试了 SimpleCursorAdapter 和一个这样的 TextView:

String[] from = new String[] DataContract.Obavijesti.OBAVIJESTI_NASLOV;
    int[]  to = new int[]  R.id.obNaslov ;

    sAdapter = new SimpleCursorAdapter(getActivity(),
            R.layout.fragment_obavijesti_row, null, from,to , 0);
    setListAdapter(sAdapter);

    getActivity().getSupportLoaderManager().initLoader(0, null, this);

但没有运气。再次输入,onLoadFinished cursor.getCount()=4,这是正确的数字

更新 2: 所以,在使用ListView lv = (ListView) getActivity().findViewById(R.id.obList);lv.setAdapter(mAdapter); 而不是setListAdapter 之后,一切正常……但现在我遇到了另一个问题。我期待主要活动(包括支持 ActionBar)首先加载,然后在加载 ListView 中的数据时显示进度条。这就是我首先实现 CursorLoader 的原因。我尝试将Thread.sleep(9000); 放入onCreateLoader 进行测试,但整个活动屏幕同时加载,因此整个UI 停止了9 秒。我做错了什么??

【问题讨论】:

您是否将光标转储到 logcat 以确保光标有数据? 是的... cursor.getCount()=4 in onLoadFinished,这正是我需要得到的 永远不会调用 bindView? 没有...还有newView也 隔离问题试试 SimpleCursorAdapter 【参考方案1】:

在回答您的第二个问题时,不要睡在onCreateLoader,这应该是快速的部分。在onLoadFinished 中休眠表示加载数据需要一段时间。

【讨论】:

我将onCreateLoader 移至onLoadFinished,但似乎这是一个市长问题***.com/questions/10608624/…...我尝试了这篇文章中的所有解决方案,但没有任何效果...我恢复使用setListAdapter(mAdapter) 和标准 @android:id/list 现在显示我的数据。但是当一切都完全加载时,整个活动就会显示出来,而不是像预期的那样工作 啊,你以为它会加载第一个,然后再加载其他的。光标适配器无法知道您何时加载了相关的。如果您想加载第一个内容并在后台加载其余内容,则必须创建自己的适配器来执行此操作。 没有。数据需要一次全部加载,但在后台加载。问题在于布局。我期待它像这样工作PICTURE 顶部工具栏和导航抽屉已生成,直到加载列表视图数据,它需要显示进度条。如果没有数据,显示“无数据”...我认为这是ListFragment的默认行为,但在我的情况下,它不起作用。 我在游标加载器中看不到任何会导致它挂起的东西。你能把你的活动放在里面吗? 是否有可能,threed.sleep() 挂起主要活动?如果是这样,我该如何测试数据的“长时间加载”?

以上是关于带有自定义 CursorAdapter 的 Android ListFragment 不显示数据的主要内容,如果未能解决你的问题,请参考以下文章

自定义 CursorLoader 和支持 ListView 的 CursorAdapter 之间的数据不同步

在 cursoradapter 中从 ListView 中删除项目

在 CursorAdapter 中使用带有 ORMLite 的 Android 游标

带有 CursorAdapter 的 Android ListView 项目 onClick 仅在一些点击后工作

如何使用 CursorAdapter 将 Filter 设置为 ListView?

如何使用CursorAdapter将Filter设置为ListView?