我正在学习自定义提供程序和加载程序。作为一个简单的例子,我正在尝试实现一个GridView
显示存储在外部 SD 卡中的图片。尽管我已经阅读了很多(文档、SO 上的主题、Google 群组、论坛......),但我无法让我的代码正常工作。我知道此示例中可能存在几个问题,但我想逐步进行。停止代码的第一个错误是 a NullPointerException
,所以我的问题是如何修复它。
这是我的最小版本Activity
(它使用支持库 v4):
public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private String[] columns = {
MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID
};
private String orderBy = MediaStore.Images.Media._ID;
private ImageAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Prepare the loader
getSupportLoaderManager().initLoader(0, null, this);
// Initialize the layout Adapter
String[] cols = new String[] {MediaStore.Images.Media.DATA};
int[] views = new int[] {R.id.thumbImage};
mAdapter = new ImageAdapter(getApplication(), R.layout.galleryitem,
null, cols, views, 0);
// Set the layout Adapter
GridView gridview = (GridView) findViewById(R.id.gallery_gridview);
gridview.setAdapter(mAdapter);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
return new CursorLoader(getApplication(), baseUri, columns,
null, null, orderBy);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader){
mAdapter.swapCursor(null);
}
}
这是我的扩展SimpleCursorAdapter
:
public class ImageAdapter extends SimpleCursorAdapter {
private int columnIndex;
private LayoutInflater mInflater;
private class ViewHolder {
ImageView imageView;
}
public ImageAdapter(Context c, int layout, Cursor aCursor, String[] from,
int[] to, int flags) {
super(c, layout, aCursor, from, to, flags);
this.mContext = c;
this.mCursor = aCursor;
mInflater = (LayoutInflater)
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {return mCursor.getCount();}
@Override
public Object getItem(int position) {return position;}
@Override
public long getItemId(int position) {return position;}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh;
View cell = convertView;
if (cell == null) {
vh = new ViewHolder();
// No View passed, create one.
cell = mInflater.inflate(R.layout.galleryitem, null);
// Populate the ViewHolder
vh.imageView = (ImageView) cell.findViewById(R.id.thumbImage);
// Store the ViewHolder inside the layout
cell.setTag(vh);
// Setup the View behavior by setting some listeners...
} else {
vh = (ViewHolder) cell.getTag();
}
// Update the cell View state
// Move the cursor to the current position
mCursor.moveToPosition(position);
// Get the current value for the requested position
columnIndex = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
int imageID = mCursor.getInt(columnIndex);
// Set the content of the image based on the provided Uri
vh.imageView.setImageURI(Uri.withAppendedPath(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" +
imageID));
return cell;
}
}
当我运行代码时,logcat在适配器NullPointerException
的方法中显示一个。getCount()
似乎没有将光标传递给适配器。
更新:
在活动中,我将 null 作为光标参数传递给适配器构造函数,因为:
- 我不知道如何获取对光标的引用,因为我正在使用
getSupportLoaderManager().initLoader()
- 由于同样的原因,在其他 SO 线程上也做了同样的事情,而且对他们来说似乎工作正常
更新:
这是 logcat 输出
08-22 09:19:44.754: I/Process(5758): Sending signal. PID: 5758 SIG: 9
08-22 09:23:16.041: D/AndroidRuntime(8691): Shutting down VM
08-22 09:23:16.041: W/dalvikvm(8691): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
08-22 09:23:16.041: E/AndroidRuntime(8691): Uncaught handler: thread main exiting due to uncaught exception
08-22 09:23:16.061: E/AndroidRuntime(8691): java.lang.RuntimeException: Unable to start activity ComponentInfo{uvesoft.com.mycustomadapter/uvesoft.com.mycustomadapter.MainActivity}: java.lang.NullPointerException
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.os.Handler.dispatchMessage(Handler.java:99)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.os.Looper.loop(Looper.java:123)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread.main(ActivityThread.java:4363)
08-22 09:23:16.061: E/AndroidRuntime(8691): at java.lang.reflect.Method.invokeNative(Native Method)
08-22 09:23:16.061: E/AndroidRuntime(8691): at java.lang.reflect.Method.invoke(Method.java:521)
08-22 09:23:16.061: E/AndroidRuntime(8691): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
08-22 09:23:16.061: E/AndroidRuntime(8691): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
08-22 09:23:16.061: E/AndroidRuntime(8691): at dalvik.system.NativeStart.main(Native Method)
08-22 09:23:16.061: E/AndroidRuntime(8691): Caused by: java.lang.NullPointerException
08-22 09:23:16.061: E/AndroidRuntime(8691): at uvesoft.com.mycustomadapter.ImageAdapter.getCount(ImageAdapter.java:34)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.widget.GridView.setAdapter(GridView.java:128)
08-22 09:23:16.061: E/AndroidRuntime(8691): at uvesoft.com.mycustomadapter.MainActivity.onCreate(MainActivity.java:37)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-22 09:23:16.061: E/AndroidRuntime(8691): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
08-22 09:23:16.061: E/AndroidRuntime(8691): ... 11 more
08-22 09:23:16.081: I/dalvikvm(8691): threadid=7: reacting to signal 3
08-22 09:23:16.081: E/dalvikvm(8691): Unable to open stack trace file '/data/anr/traces.txt': Permission denied
我真的很感激任何帮助。TIA