0

我写了下列类来创建一个具有自定义列表行的列表视图。我使用Android支持库v4作为项目和ActionBarSherlock库来集成旧设备的操作栏。ListFragment:CursorAdapter中的findViewById返回null

public class CustomListActivity extends SherlockFragmentActivity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     setTheme(R.style.Sherlock___Theme_DarkActionBar); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.fragment_list); 
    } 
} 

...

public class ListFragment extends SherlockListFragment implements LoaderCallbacks<Cursor> { 
    private Activity mActivity; 
    private CursorAdapter mAdapter; 
    // Query parameter as members ... 
    private String mFromColumns; 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     setEmptyText("No data to display"); 
     mActivity = getActivity(); 
     // Query parameters are stored in members here ... 
     mFromColumns = { "_id", "name" }; 
     mAdapter = new CustomCursorAdapter(mActivity, null, 0); 
     setListAdapter(mAdapter); 
     getLoaderManager().initLoader(0, null, this); 
    } 

    @Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle extras) { 
     return new CursorLoader(mActivity, mUri, mFromColumns, mSelection, mSelectionArgs, sortOrder); 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
     mAdapter.swapCursor(cursor); 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> loader) { 
     mAdapter.swapCursor(null); 
    } 
} 

...

public class CustomCursorAdapter extends CursorAdapter { 
    private LayoutInflater mInflater; 

    public CustomCursorAdapter(Context context, Cursor cursor, int flags) { 
     super(context, cursor, flags); 
     mInflater = LayoutInflater.from(context); 
    } 

    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     TextView listItem = (TextView)view.findViewById(R.id.name); 
//  TextView listItem = (TextView)view.findViewById(android.R.id.text1); 
     String text = cursor.getString(cursor.getColumnIndex("name")); 
     listItem.setText(text); 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     return mInflater.inflate(R.layout.list_item, parent, false); 
//  return mInflater.inflate(android.R.layout.simple_list_item_1, parent, false); 
    } 
} 

列表视图成功地加载和显示数据行,当我使用了框架提供的列表项和布局(未注释行CustomCursorAdapter)。但是,当我交换行来使用我的自定义布局和列表项时,findViewById返回null。这里是xml文件。

fragment_list.xml

<?xml version="1.0" encoding="utf-8"?> 
<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
    android:name="com.example.app.fragment.ListFragment" 
    android:id="@+id/list_fragment" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

</fragment> 

list_item.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 
    <TextView 
     android:id="@+id/name" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"> 
    </TextView> 
</LinearLayout> 

我敢肯定,问题是我如何连接的XML文件或他们是如何构建。我希望你能看到错误。实际上,我不明白如何使用list_item.xml作为列表视图的行布局。我设置为fragment_list.xml的唯一参考是通过setContentView(R.layout.fragment_list);。而这个XML文件不包含任何容器元素,如<ListView android:id="@android:id/list" />(我在其他设置中看到)。

此外:

我想知道,如果它仍然建议使用ViewHolder模式在CursorAdapter如果此行为是内置了。我在其他例子中多次看到它,但是从BaseAdapterSimpleCursorAdapter继承的那些。


教训:

当我试图解决这个问题,我有权利设置somewhen的XML文件。但另一件事阻碍了我让事情继续下去。这是你需要注意的。
如果要在行布局中显示多个信息,请在CursorLoaderfromColumn参数中包含关联的列名称,这一点很重要。否则,你会遇到一个例外:

java.lang.IllegalStateException: get field slot from row 0 col -1 failed 
在fromColumns

每列名...

String[] fromColumns = { "_id", "name", "comments" } 

...是关系到你的要求光标。 _id列必须使用游标作为迭代器。

String name = cursor.getString(cursor.getColumnIndex("name")); 
String comment = cursor.getString(cursor.getColumnIndex("comment")); 
+0

有相同的空问题。我只是意识到,构造函数中的行布局在newView方法中不一样。所以我在定位id的时候,在膨胀视图时不在行布局中。 – 2014-12-01 20:35:27

回答

2

您的代码在两种情况下都适用于我(因为和当我更改行注释时)。唯一的事情是:我已将公共空构造函数添加到ListFragment

而且还建议使用ViewHolder模式与CursorAdapter

public void bindView(View view, Context context, Cursor cursor) { 
    ViewHolder holder = (ViewHolder) view.getTag(); 
    if (holder == null) { 
     holder = new ViewHolder(); 
     holder.name = (TextView) view.findViewById(R.id.name); 

     view.setTag(holder); 
    } 

    String text = cursor.getString(cursor.getColumnIndex("name")); 
    holder.name.setText(text); 
} 

private static class ViewHolder { 
    TextView name; 
} 
+0

您引用了实际上按照上述说明工作的未注释行。关于* ViewHolder * patterm:你可以添加一个关于如何将它与我的代码一起使用的例子吗? – JJD 2012-08-01 21:05:57

+0

@JJD,对不起,我更正了我的答案。 – StenaviN 2012-08-01 21:43:27

+0

当一个人坐在电脑前整整一天时,就会发生这种情况。谢天谢地,我昨天早上被迫上床睡觉。今天,我意识到我引用了'.inflate(R.layout.wrong_xml,...“中的前一个XML布局,谢谢StenaviN。 – JJD 2012-08-02 09:21:57