如何在使用自定义 CursorAdapter 和 Cursor Loader 时让 GridView 和 GridView 项目在片段中膨胀?
How to get GridView and GridView Item to Inflate in a Fragment while using Custom CursorAdapter and Cursor Loader?
我是 Android 编程和 Whosebug 的新手。我正在开发一个包含多个活动的 journal/tracking 应用程序,该应用程序需要用户输入以获取数据并由内部 SQLite 数据库支持。我正在使用自定义 CursorAdapter,因此我可以对图像和加载程序管理器进行调整,以在 UI 线程之外管理数据库。
我遇到的困难是让 GridView 在我的主要 activity 的一个片段中膨胀。数据库插入似乎工作正常,但是 GridView 没有膨胀,我只看到一个空白屏幕(背景显示)。我已经尝试更改片段容器和布局参数,但这些会导致错误并且仍然没有 GridView。我已尝试调整 CursorAdaptor 参数 - 包括 null、this 或 getContext。我试过仅按布局附加片段并以编程方式附加。我的片段附件中可能有错误,因为我仍然不确定这一点。我已经包含了很多代码,因为我不知道问题出在哪里。
我目前在项目构建中没有收到任何错误。对我做错了什么有什么想法吗?将不胜感激。
这是我的主要 Activity,它有两个片段 MyCritter 和 KeepMyCritters(GridView)。我省略了工具栏和按钮 - 这些工作正常。
public class MyCritter extends Critters implements KeepMyCritters.OnFragmentInteractionListener,LoaderManager.LoaderCallbacks<Cursor> {
private KeepMyCritters critterFragment;
private Intent intent;
public CursorAdapter cursorAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_critters);
cursorAdapter = new CritterCursorAdapter(this, null, 0);
getSupportLoaderManager().initLoader(0,null,this);
InsertNewCritter(_id, "Sherman");
InsertNewCritter(_id,"Charlie");
critterFragment = new KeepMyCritters();
setFragment(critterFragment);
}
public void setFragment(Fragment frag){
FragmentManager fm = getSupportFragmentManager();
fm.findFragmentById(R.id.container);
if (frag == null) {fm.beginTransaction().add(R.id.container, critterFragment).commit();
}
@Override
public void onFragmentInteraction(long _id) {
Toast.makeText(getApplicationContext(),"You selected a Critter to View", Toast.LENGTH_LONG).show();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
CursorLoader cursorLoader = new CursorLoader(this, CritterProvider.CONTENT_URI, null, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
}
这是我的 KeepMyCritters 片段
public class KeepMyCritters extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>,AdapterView.OnItemClickListener{
CritterCursorAdapter cursorAdapter;
private OnFragmentInteractionListener mListener;
public KeepMyCritters() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_keep_my_critters, container, false);
cursorAdapter = new CritterCursorAdapter(getContext(), (Cursor)CritterProvider.CONTENT_URI,0);
GridView gv =(GridView) view.findViewById(R.id.gridview);
gv.setAdapter(cursorAdapter);
gv.setOnItemClickListener(this);
getLoaderManager().initLoader(0,null,this);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach(){
super.onDetach();
mListener=null;
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Uri CritterUri = ContentUris.withAppendedId(CritterProvider.CONTENT_URI, l );
if(mListener !=null) {
mListener.onFragmentInteraction(l);
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getContext(), CritterProvider.CONTENT_URI, null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
cursorAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(long id);
}
}
这是我自定义的 CursorAdapter class
public class CritterCursorAdapter extends CursorAdapter {
public CritterCursorAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
}
Context c;
private LayoutInflater inflater;
private GridView gv;
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return inflater.inflate(R.layout.fragment_item_grid, gv);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String name = cursor.getString(
cursor.getColumnIndex(CritterDatabaseHelper.NAME));
TextView hName = (TextView) view.findViewById(R.id.critterName);
hName.setText(name);
}
}
数据库有一个 _id 列,在调试器中它显示条目已正确插入。
insertCritter代码:
protected void InsertNewCritter(int _id, String name) {
ContentValues values = new ContentValues();
values.put(CrittersDatabaseHelper.NAME, name);
Uri crittersUri = getContentResolver().insert(CritterProvider.CONTENT_URI, values);
Log.d("MyCritter", "Inserted data " + crittersUri.getLastPathSegment());
}
内容提供者:
public class CritterProvider extends ContentProvider {
private static final String AUTHORITY = mypackage.critterProvider";
private static final String BASE_PATH = "critters";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
private static final int CRITTERS = 1;
private static final int CRITTERS_ID = 2;
private static final UriMatcher uriMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
static {
uriMatcher.addURI(AUTHORITY, BASE_PATH, CRITTERS);
uriMatcher.addURI(AUTHORITY, BASE_PATH + " /# ", CRITTERS_ID);
}
private SQLiteDatabase db;
@Override
public boolean onCreate() {
CrittersDatabaseHelper cdb = new CrittersDatabaseHelper(getContext());
db = cdb.getWritableDatabase();
return true;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String selection, String[] selectionArgs, String sortOrder) {
return db.query(CrittersDatabaseHelper.TABLE_MAIN, CrittersDatabaseHelper.ALL_TABLE_MAIN_COLUMNS, selection, selectionArgs, null, null, null);
}
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
long id = db.insert(CrittersDatabaseHelper.TABLE_MAIN, null, values);
return Uri.parse(BASE_PATH + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return db.delete(CrittersDatabaseHelper.TABLE_MAIN, selection, selectionArgs);
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return db.update(CrittersDatabaseHelper.TABLE_MAIN, values, selection, selectionArgs);
}
}
最后是布局文件:
MyCritter(主要Activity)xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="@color/colorPrimaryDark"
tools:context="com.mypackage.Activities.MyCritters">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="@layout/content_my_critter"
android:layout_height="match_parent"
android:layout_width="422dp" />
<include layout="@layout/fragment_keep_my_critters"
android:layout_height="match_parent"
android:layout_width="422dp"/>
</LinearLayout>
</HorizontalScrollView>
KeepMyCritters 片段xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/jungle"
tools:context="com.mypackage.Fragments.KeepMyCritters"
tools:showIn="@layout/activity_my_critter">
<TextView
android:text="My Critters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:gravity="center"
android:textColor="@color/colorAccent" />
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="546dp"
android:columnWidth="120dp"
android:numColumns="auto_fit"
android:verticalSpacing="30dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_alignParentBottom="true" />
</FrameLayout>
我的 gridview - 项目 xml:
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_item_grid"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:showIn="@layout/fragment_keep_my_critters">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/critterName"
android:layout_weight="1"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:gravity="center"
android:textColor="#3bae1b"
android:textStyle="normal|bold|italic" />
</LinearLayout>
我认为问题是我在 GridView 中使用了协调器布局。我现在看到以前的帖子解释协调器布局和 Gridview 不能一起工作。提出了几种解决方法,但我无法弄清楚如何在我的特定项目中实施这些方法。我取消了协调器布局并让 gridview 正常工作。我在尝试将 uri 投射到游标适配器中的游标时确实遇到了问题,我更改了游标适配器以使其正常工作。我仍然对其他解决方案持开放态度,因为协调器布局流畅且更精确。
我是 Android 编程和 Whosebug 的新手。我正在开发一个包含多个活动的 journal/tracking 应用程序,该应用程序需要用户输入以获取数据并由内部 SQLite 数据库支持。我正在使用自定义 CursorAdapter,因此我可以对图像和加载程序管理器进行调整,以在 UI 线程之外管理数据库。
我遇到的困难是让 GridView 在我的主要 activity 的一个片段中膨胀。数据库插入似乎工作正常,但是 GridView 没有膨胀,我只看到一个空白屏幕(背景显示)。我已经尝试更改片段容器和布局参数,但这些会导致错误并且仍然没有 GridView。我已尝试调整 CursorAdaptor 参数 - 包括 null、this 或 getContext。我试过仅按布局附加片段并以编程方式附加。我的片段附件中可能有错误,因为我仍然不确定这一点。我已经包含了很多代码,因为我不知道问题出在哪里。
我目前在项目构建中没有收到任何错误。对我做错了什么有什么想法吗?将不胜感激。
这是我的主要 Activity,它有两个片段 MyCritter 和 KeepMyCritters(GridView)。我省略了工具栏和按钮 - 这些工作正常。
public class MyCritter extends Critters implements KeepMyCritters.OnFragmentInteractionListener,LoaderManager.LoaderCallbacks<Cursor> {
private KeepMyCritters critterFragment;
private Intent intent;
public CursorAdapter cursorAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_critters);
cursorAdapter = new CritterCursorAdapter(this, null, 0);
getSupportLoaderManager().initLoader(0,null,this);
InsertNewCritter(_id, "Sherman");
InsertNewCritter(_id,"Charlie");
critterFragment = new KeepMyCritters();
setFragment(critterFragment);
}
public void setFragment(Fragment frag){
FragmentManager fm = getSupportFragmentManager();
fm.findFragmentById(R.id.container);
if (frag == null) {fm.beginTransaction().add(R.id.container, critterFragment).commit();
}
@Override
public void onFragmentInteraction(long _id) {
Toast.makeText(getApplicationContext(),"You selected a Critter to View", Toast.LENGTH_LONG).show();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
CursorLoader cursorLoader = new CursorLoader(this, CritterProvider.CONTENT_URI, null, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
}
这是我的 KeepMyCritters 片段
public class KeepMyCritters extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>,AdapterView.OnItemClickListener{
CritterCursorAdapter cursorAdapter;
private OnFragmentInteractionListener mListener;
public KeepMyCritters() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_keep_my_critters, container, false);
cursorAdapter = new CritterCursorAdapter(getContext(), (Cursor)CritterProvider.CONTENT_URI,0);
GridView gv =(GridView) view.findViewById(R.id.gridview);
gv.setAdapter(cursorAdapter);
gv.setOnItemClickListener(this);
getLoaderManager().initLoader(0,null,this);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach(){
super.onDetach();
mListener=null;
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Uri CritterUri = ContentUris.withAppendedId(CritterProvider.CONTENT_URI, l );
if(mListener !=null) {
mListener.onFragmentInteraction(l);
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getContext(), CritterProvider.CONTENT_URI, null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
cursorAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(long id);
}
}
这是我自定义的 CursorAdapter class
public class CritterCursorAdapter extends CursorAdapter {
public CritterCursorAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
}
Context c;
private LayoutInflater inflater;
private GridView gv;
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return inflater.inflate(R.layout.fragment_item_grid, gv);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String name = cursor.getString(
cursor.getColumnIndex(CritterDatabaseHelper.NAME));
TextView hName = (TextView) view.findViewById(R.id.critterName);
hName.setText(name);
}
}
数据库有一个 _id 列,在调试器中它显示条目已正确插入。
insertCritter代码:
protected void InsertNewCritter(int _id, String name) {
ContentValues values = new ContentValues();
values.put(CrittersDatabaseHelper.NAME, name);
Uri crittersUri = getContentResolver().insert(CritterProvider.CONTENT_URI, values);
Log.d("MyCritter", "Inserted data " + crittersUri.getLastPathSegment());
}
内容提供者:
public class CritterProvider extends ContentProvider {
private static final String AUTHORITY = mypackage.critterProvider";
private static final String BASE_PATH = "critters";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
private static final int CRITTERS = 1;
private static final int CRITTERS_ID = 2;
private static final UriMatcher uriMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
static {
uriMatcher.addURI(AUTHORITY, BASE_PATH, CRITTERS);
uriMatcher.addURI(AUTHORITY, BASE_PATH + " /# ", CRITTERS_ID);
}
private SQLiteDatabase db;
@Override
public boolean onCreate() {
CrittersDatabaseHelper cdb = new CrittersDatabaseHelper(getContext());
db = cdb.getWritableDatabase();
return true;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String selection, String[] selectionArgs, String sortOrder) {
return db.query(CrittersDatabaseHelper.TABLE_MAIN, CrittersDatabaseHelper.ALL_TABLE_MAIN_COLUMNS, selection, selectionArgs, null, null, null);
}
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
long id = db.insert(CrittersDatabaseHelper.TABLE_MAIN, null, values);
return Uri.parse(BASE_PATH + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return db.delete(CrittersDatabaseHelper.TABLE_MAIN, selection, selectionArgs);
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return db.update(CrittersDatabaseHelper.TABLE_MAIN, values, selection, selectionArgs);
}
}
最后是布局文件:
MyCritter(主要Activity)xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="@color/colorPrimaryDark"
tools:context="com.mypackage.Activities.MyCritters">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="@layout/content_my_critter"
android:layout_height="match_parent"
android:layout_width="422dp" />
<include layout="@layout/fragment_keep_my_critters"
android:layout_height="match_parent"
android:layout_width="422dp"/>
</LinearLayout>
</HorizontalScrollView>
KeepMyCritters 片段xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/jungle"
tools:context="com.mypackage.Fragments.KeepMyCritters"
tools:showIn="@layout/activity_my_critter">
<TextView
android:text="My Critters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:gravity="center"
android:textColor="@color/colorAccent" />
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="546dp"
android:columnWidth="120dp"
android:numColumns="auto_fit"
android:verticalSpacing="30dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_alignParentBottom="true" />
</FrameLayout>
我的 gridview - 项目 xml:
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_item_grid"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:showIn="@layout/fragment_keep_my_critters">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/critterName"
android:layout_weight="1"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:gravity="center"
android:textColor="#3bae1b"
android:textStyle="normal|bold|italic" />
</LinearLayout>
我认为问题是我在 GridView 中使用了协调器布局。我现在看到以前的帖子解释协调器布局和 Gridview 不能一起工作。提出了几种解决方法,但我无法弄清楚如何在我的特定项目中实施这些方法。我取消了协调器布局并让 gridview 正常工作。我在尝试将 uri 投射到游标适配器中的游标时确实遇到了问题,我更改了游标适配器以使其正常工作。我仍然对其他解决方案持开放态度,因为协调器布局流畅且更精确。