CursorLoader不在Fragment中显示数据

时间:2012-11-13 21:19:03

标签: android android-fragments android-contentprovider android-cursorloader

我有一个应用程序执行以下操作:带有ListView的Activity显示三个项目:Beginning,Intermediate,Advanced。根据用户的选择,应用程序应转到带有ListView的片段,该列表显示基础SQLiteDatabase中Level = Beginning或Intermediate或Advanced的所有项目。第二步不适合我。我已经通过调试器验证了我的数据库中有数据,所以这不是问题所在。这是我在初始Activity中的代码 - 这是来自onItemClick方法:

final String[] values = new String[] {
            "Beginning", "Intermediate", "Advanced"
    };
public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            Intent choice = new Intent(getApplicationContext(), com.MyKnitCards.project.StitchList.class);
            Bundle dataBundle = new Bundle();
            String chosenValue = values[position];
            dataBundle.putString("Level",chosenValue);
            choice.putExtras(dataBundle);
            try {
                startActivity(choice);
}
        }

这是StitchList类,它是Fragment类,在上面的代码中引用:

public class StitchList extends FragmentActivity {
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.stitchfragment);
}

}

这是Fragment的XML文件,名为stitchfragment.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment android:id="@+id/frag_stitchlist"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
class="com.MyKnitCards.project.ListFrag" />
<fragment android:id="@+id/frag_stitchdetail"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.MyKnitCards.project.DetailFrag" />
</LinearLayout>

这是ListFrag类。我正在使用支持库和带有ContentProvider的CursorLoader,名为StitchProvider; SQLiteDatabase称为SQLData:

public class ListFrag<Cursor> extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

private static final String STITCHTABLE_BASEPATH = "MyStitches_tbl";
private static final String AUTHORITY = "com.MyKnitCards.project.SQLData";
public static final Uri STITCHES_URI = Uri.parse("content://" + AUTHORITY + "/" + STITCHTABLE_BASEPATH);
private static final String[] PROJECTION = new String[] { "_id", "stitchname" };
private SimpleCursorAdapter mAdapter;
private static final int LOADER_ID = 0;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    Intent myData = getActivity().getIntent();
    Bundle info = myData.getExtras();   

    String[] dataColumns = { "stitchname", "_id" };
    int[] viewIDs = { R.id.frag_stitchlist };
    mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, null, dataColumns, viewIDs, 0);
    setListAdapter(mAdapter);
    getLoaderManager().initLoader(0, info, (LoaderCallbacks<Cursor>) this); 

}

public void onListItemClick(ListView l, View v, int position, long id) {
    String item = (String) getListAdapter().getItem(position);
    DetailFrag frag = (DetailFrag) getFragmentManager().findFragmentById(R.id.frag_stitchdetail);
    if (frag != null && frag.isInLayout()) {
        frag.setText(item);
    }
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String selection = "stitchlevel='" + args.getString("Level") + "'";
    return (Loader<Cursor>) new CursorLoader(getActivity(), STITCHES_URI,
            PROJECTION, selection, null, null); 
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    switch (loader.getId()) {
      case LOADER_ID:
        mAdapter.swapCursor((android.database.Cursor) cursor);
        break;
    }

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

}

}

onListItemClick方法用于在细节片段中显示数据,但我从来没有这么做过。从不显示基于Intent中的数据从数据库中检索的项目列表。

我想到了一些可能的问题:

1)onCreateLoader方法中查询的语法是否正确?例如,它应该是“stitchlevel ='Beginning'”。我知道args.getString(“Level”)中的数据是有效的,因为我在调试器中跟着它,但这里的语法是否正确?我假设它应该是标准的SQL语法,但是...... 2)在Fragment的onActivityCreated方法中为viewID分配值时,我指的是正确的位置吗? 3)同样,在下一行,SimpleCursorAdapter,android.R.layout.simple_list_item_1在这里是否正确?或者它应该是R.layout.stitchfragment? 4)我在ContentProvider的查询方法上放了一个断点,我从未点过断点。创建CursorLoader时不应该吗?此外,如果我在List Fragment的onLoadFinished方法上放置一个断点,则游标为null。我错过了什么 5)我被告知片段的onActivityCreated方法中的dataColumns应该包含我的表的_id列。真的吗?这对我来说似乎很奇怪,因为列表只显示一条信息:stitchname。但是,无论是否包含_id,片段列表都不会显示任何内容 6)我是否应该通过getLoaderManager.initLoader将Bundle,info传递给CursorLoader,就像在Fragment的onActivityCreatedMethod中一样? 7)我已经看到了在Fragment的onActivityCreated方法中的getLoaderManager()。initLoader()之前调用setListAdapter的例子,并且我看过后面调用setListAdapter的例子。哪个是对的?似乎都没有帮助我......

如果我只是这样做,我就可以显示片段:

Intent myData = getActivity().getIntent();
    Bundle info = myData.getExtras();
    String level = info.getString("Level");
    String[] values = new String[] {level, level};
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, values);
    setListAdapter(adapter);

所以我知道我可以在片段中显示数据;它似乎没有使用CursorLoader和ContentProvider。我希望这不是信息过载;道歉,如果是的话。如果有人有任何想法,我将非常感激。

1 个答案:

答案 0 :(得分:1)

  

1)onCreateLoader方法中查询的语法是否正确?它   应该阅读,例如,“stitchlevel ='Beginning'”。我知道数据   在args.getString(“Level”)中有效,因为我已经完成了它   在调试器中,但这里的语法是否正确?我在假设它   应该是标准的SQL语法,但

是的,这是对的。更好的是:

String selection = "stitchlevel= ?";
String selectionArgs = new String[] {args.getString("Level")};
return new CursorLoader(getActivity(), STITCHES_URI, PROJECTION, selection, selectionArgs, null); 
  

2)在片段中为viewID分配值   onActivityCreated方法,我指的是正确的地方吗? 3)   同样,在下一行中,SimpleCursorAdapter是   android.R.layout.simple_list_item_1在这里更正?或者也许应该   是R.layout.stitchfragment?

没有。您提供给适配器的int数组表示适配器中使用的行布局中的ID,而不是您编写的片段的ID。如果您使用android.R.layout.simple_list_item_1(仅包含TextView),则必须提供id的{​​{1}},即TextView

android.R.id.text1
  

4)我在ContentProvider的查询方法上放了一个断点,我从来没有   打破了断点。创建CursorLoader时不应该吗?   此外,如果我在List Fragment上放置一个断点   onLoadFinished方法,游标为null。我缺少什么

我认为你在上一个问题上没有做我推荐你的事。应该至少调用提供者的String[] dataColumns = { "stitchname"}; int[] viewIDs = { android.R.id.text1 }; mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, null, dataColumns, viewIDs, 0); 方法,并且这种情况不会发生,只留下一个选项。我注意到你施放了query而你错过了来自Loaders的回调方法的Override注释。将LoaderManager.LoaderCalbbacks注释添加到这些方法中:

Override

看看会发生什么。如果出现错误,请确保使用了正确的导入,并且只使用兼容包中的类或普通的类(您可以轻松地从文件中删除所有导入,然后重新导入所有内容并使用{{1}的类})。只是一个疯狂的猜测。

  

5)我被告知Fragment的onActivityCreated中的dataColumns   方法应该包含我的表的_id列。真的吗?它似乎   对我来说很奇怪,因为列表只显示一条信息:   stitchname。但是,无论是否包含_id,都是   片段列表不显示任何内容

基于

@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { String selection = "stitchlevel= ?"; String selectionArgs = new String[] {args.getString("Level")}; return new CursorLoader(getActivity(), STITCHES_URI, PROJECTION, selection, selectionArgs, null); } 的适配器要求使用的android.support.v4必须包含名为Cursorsee the documentation of the CursorAdapter class的列,Cursor的超类。它不需要出现在设置到适配器中的_id数组中。

  

6)将Bundle,info传递给CursorLoader是否合适   通过getLoaderManager.initLoader,就像我在Fragment中所做的那样   onActivityCreatedMethod?

是。但是关于id,要保持一致,如果你打算使用SimpleCursorAdapter在任何地方使用它,而不仅仅是在你的代码中的某些地方。或者甚至更好,如果您只使用一个String,只需在任何地方使用LOADER_ID(因此无需在Loader方法中测试0

  

7)我见过之前调用过setListAdapter的例子   片段的onActivityCreated中的getLoaderManager()。initLoader()   方法和我见过的例子,其中调用了setListAdapter。   哪个是对的?

两者都可以使用。我会设置适配器,然后初始化LOADER_ID