我正在撰写FragmentActivity
我有ListFragment
(使用SimpleCursorAdapter
), detailsFragment 和 detailActivity (在手机处于人像状态时使用,嵌入 detailsFragment )
当我单击列表中的一个项目时,它应该使用来自第二个游标的数据填充 detailFragment ,使用所选项目的_id
作为selectionArgs构建。
但是,_id
似乎没有通过,我在ListFragment
举杯祝酒,我展示了所选项目的_id
(并且它是正确的),但是在 detailsFragment _id
永远不会到达(它保持等于0
,发送NullPointerException
)。
我在哪里误会?
家长活动
package com.gmail.david.corsalini.sportscout;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MatchesRugbyPage extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.matches_rugby);
}
}
MatchesListFragment(我的ListFragment)
package com.gmail.david.corsalini.sportscout;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
/**
* This is the "top-level" fragment, showing a list of items that the user can
* pick. Upon picking an item, it takes care of displaying the data to the user
* as appropriate based on the current UI layout.
*/
public class MatchesListFragment extends ListFragment {
boolean mDualPane;
private Cursor cursor;
private SimpleCursorAdapter myAdapter;
private long MATCH_ID;
private int selected;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Database
DBSportScout db = new DBSportScout(getActivity());
db.open();
// Cursor
String[] selection = { DBSportScout.MatchMetaData.KEY_MNAME,
DBSportScout.MatchMetaData.KEY_MROWID };
cursor = db.fetch(DBSportScout.MatchMetaData.DATABASE_TABLE_MATCH,
selection, null, null, null, null, null, null);
getActivity().startManagingCursor(cursor);
// Adapter
String[] columns = { DBSportScout.MatchMetaData.KEY_MNAME };
int[] to = { R.id.tv1ListItem };
myAdapter = new SimpleCursorAdapter(getActivity(),
R.layout.ss_list_item, cursor, columns, to);
setListAdapter(myAdapter);
db.close();
// Check to see if we have a frame in which to embed the details
// fragment directly in the containing UI.
View detailsFrame = getActivity().findViewById(R.id.detailsFrame);
mDualPane = detailsFrame != null
&& detailsFrame.getVisibility() == View.VISIBLE;
if (savedInstanceState != null) {
// Restore last state for checked position.
MATCH_ID = savedInstanceState.getLong("curChoice", 0);
}
if (mDualPane) {
// In dual-pane mode, the list view highlights the selected item.
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Make sure our UI is in the correct state.
showDetails(MATCH_ID);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong("curChoice", MATCH_ID);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
selected = position;
MATCH_ID = myAdapter.getItemId(position);
Toast.makeText(getActivity(), "Partita n. " + Long.toString(MATCH_ID),
Toast.LENGTH_SHORT).show();
showDetails(MATCH_ID);
Log.i("Partita", "ID Partita selezionata= " + MATCH_ID);
}
/**
* Helper function to show the details of a selected item, either by
* displaying a fragment in-place in the current UI, or starting a whole new
* activity in which it is displayed.
*/
public void showDetails(long matchid) {
if (mDualPane) {
// We can display everything in-place with fragments, so update
// the list to highlight the selected item and show the data.
getListView().setItemChecked(selected, true);
// Check what fragment is currently shown, replace if needed.
MatchDetailsFragment f = (MatchDetailsFragment) getFragmentManager()
.findFragmentById(R.id.detailsFrame);
if (f == null || f.getMATCH_ID() != matchid) {
// Make new fragment to show this selection.
f = new MatchDetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putLong("matchid", matchid);
f.setArguments(args);
// Execute a transaction, replacing any existing fragment
// with this one inside the frame.
FragmentTransaction ft = getFragmentManager()
.beginTransaction();
ft.replace(R.id.detailsFrame, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
} else {
// Otherwise we need to launch a new activity to display
// the dialog fragment with selected text.
Intent intent = new Intent();
intent.setClass(getActivity(), MatchDetailsActivity.class);
intent.putExtra("index", matchid);
startActivity(intent);
}
}
}
MatchDetailFragment(my detailsFragment)
package com.gmail.david.corsalini.sportscout;
import com.gmail.david.corsalini.sportscout.DBSportScout.MatchMetaData;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
/**
* This is the secondary fragment, displaying the details of a particular item.
*/
public class MatchDetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to show the text at
* 'matchid'.
*/
public static MatchDetailsFragment newInstance(long matchid) {
MatchDetailsFragment f = new MatchDetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putLong("matchid", matchid);
f.setArguments(args);
return f;
}
private TextView tvfTriesA;
private TextView tvfTriesB;
private TextView tvfName;
private long MATCH_ID;
public long getMATCH_ID() {
MATCH_ID = getArguments().getLong("matchid", 0);
return MATCH_ID;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
// We have different layouts, and in one of them this
// fragment's containing frame doesn't exist. The fragment
// may still be created from its saved state, but there is
// no reason to try to create its view hierarchy because it
// won't be displayed. Note this is not needed -- we could
// just run the code below, where we would create and return
// the view hierarchy; it would just never be used.
return null;
}
View view = inflater.inflate(R.layout.match_summary, container, false);
populateDetails(MATCH_ID);
return view;
}
public void populateDetails(long matchid) {
// Create textviews
tvfName = (TextView) getActivity().findViewById(R.id.tvfName);
tvfTriesA = (TextView) getActivity().findViewById(R.id.tvfTriesA);
tvfTriesB = (TextView) getActivity().findViewById(R.id.tvfTriesB);
tvfName.setText(Long.toString(MATCH_ID));
// Populate textviews
DBSportScout db = new DBSportScout(getActivity());
db.open();
String selectionmatchid = Long.toString(matchid);
String[] columns = { DBSportScout.MatchMetaData.KEY_MNAME,
DBSportScout.MatchMetaData.KEY_MDATE,
DBSportScout.MatchMetaData.KEY_MSTATUS,
DBSportScout.MatchMetaData.KEY_MSUMMARY,
DBSportScout.MatchMetaData.KEY_MTEAM_A_ID,
DBSportScout.MatchMetaData.KEY_MTEAM_B_ID,
DBSportScout.MatchMetaData.KEY_MCHAMP_ID,
DBSportScout.MatchMetaData.KEY_MTURN,
DBSportScout.MatchMetaData.KEY_MSPORT_ID,
DBSportScout.MatchMetaData.KEY_MSCORE_A,
DBSportScout.MatchMetaData.KEY_MSCORE_B,
DBSportScout.MatchMetaData.KEY_MSTAT1_A,
DBSportScout.MatchMetaData.KEY_MSTAT1_B,
DBSportScout.MatchMetaData.KEY_MSTAT2_A,
DBSportScout.MatchMetaData.KEY_MSTAT2_B,
DBSportScout.MatchMetaData.KEY_MSTAT3_A,
DBSportScout.MatchMetaData.KEY_MSTAT3_B,
DBSportScout.MatchMetaData.KEY_MSTAT4_A,
DBSportScout.MatchMetaData.KEY_MSTAT4_B,
DBSportScout.MatchMetaData.KEY_MSTAT5_A,
DBSportScout.MatchMetaData.KEY_MSTAT5_B,
DBSportScout.MatchMetaData.KEY_MSTAT6_A,
DBSportScout.MatchMetaData.KEY_MSTAT6_B,
DBSportScout.MatchMetaData.KEY_MSTAT7_A,
DBSportScout.MatchMetaData.KEY_MSTAT7_B,
DBSportScout.MatchMetaData.KEY_MSTAT8_A,
DBSportScout.MatchMetaData.KEY_MSTAT8_B,
DBSportScout.MatchMetaData.KEY_MSTAT9_A,
DBSportScout.MatchMetaData.KEY_MSTAT9_B,
DBSportScout.MatchMetaData.KEY_MSTAT10_A,
DBSportScout.MatchMetaData.KEY_MSTAT10_B,
DBSportScout.MatchMetaData.KEY_MSTAT11_A,
DBSportScout.MatchMetaData.KEY_MSTAT11_B,
DBSportScout.MatchMetaData.KEY_MSTAT12_A,
DBSportScout.MatchMetaData.KEY_MSTAT12_B,
DBSportScout.MatchMetaData.KEY_MSTAT13_A,
DBSportScout.MatchMetaData.KEY_MSTAT13_B,
DBSportScout.MatchMetaData.KEY_MSTAT14_A,
DBSportScout.MatchMetaData.KEY_MSTAT14_B,
DBSportScout.MatchMetaData.KEY_MSTAT15_A,
DBSportScout.MatchMetaData.KEY_MSTAT15_B,
DBSportScout.MatchMetaData.KEY_MSTAT16_A,
DBSportScout.MatchMetaData.KEY_MSTAT16_B,
DBSportScout.MatchMetaData.KEY_MSTAT17_A,
DBSportScout.MatchMetaData.KEY_MSTAT17_B,
DBSportScout.MatchMetaData.KEY_MSTAT18_A,
DBSportScout.MatchMetaData.KEY_MSTAT18_B,
DBSportScout.MatchMetaData.KEY_MSTAT19_A,
DBSportScout.MatchMetaData.KEY_MSTAT19_B,
DBSportScout.MatchMetaData.KEY_MSTAT20_A,
DBSportScout.MatchMetaData.KEY_MSTAT20_B,
DBSportScout.MatchMetaData.KEY_MSTAT21_A,
DBSportScout.MatchMetaData.KEY_MSTAT21_B,
DBSportScout.MatchMetaData.KEY_MSTAT22_A,
DBSportScout.MatchMetaData.KEY_MSTAT22_B,
DBSportScout.MatchMetaData.KEY_MSTAT23_A,
DBSportScout.MatchMetaData.KEY_MSTAT23_B,
DBSportScout.MatchMetaData.KEY_MSTAT24_A,
DBSportScout.MatchMetaData.KEY_MSTAT24_B,
DBSportScout.MatchMetaData.KEY_MSTAT25_A,
DBSportScout.MatchMetaData.KEY_MSTAT25_B,
DBSportScout.MatchMetaData.KEY_MSTAT26_A,
DBSportScout.MatchMetaData.KEY_MSTAT26_B,
DBSportScout.MatchMetaData.KEY_MSTAT27_A,
DBSportScout.MatchMetaData.KEY_MSTAT27_B,
DBSportScout.MatchMetaData.KEY_MSTAT28_A,
DBSportScout.MatchMetaData.KEY_MSTAT28_B,
DBSportScout.MatchMetaData.KEY_MSTAT29_A,
DBSportScout.MatchMetaData.KEY_MSTAT29_B,
DBSportScout.MatchMetaData.KEY_MSTAT30_A,
DBSportScout.MatchMetaData.KEY_MSTAT30_B,
DBSportScout.MatchMetaData.KEY_MSTAT31_A,
DBSportScout.MatchMetaData.KEY_MSTAT31_B,
DBSportScout.MatchMetaData.KEY_MSTAT32_A,
DBSportScout.MatchMetaData.KEY_MSTAT32_B,
DBSportScout.MatchMetaData.KEY_MSTAT33_A,
DBSportScout.MatchMetaData.KEY_MSTAT33_B,
DBSportScout.MatchMetaData.KEY_MSTAT34_A,
DBSportScout.MatchMetaData.KEY_MSTAT34_B,
DBSportScout.MatchMetaData.KEY_MSTAT35_A,
DBSportScout.MatchMetaData.KEY_MSTAT35_B,
DBSportScout.MatchMetaData.KEY_MSTAT36_A,
DBSportScout.MatchMetaData.KEY_MSTAT36_B,
DBSportScout.MatchMetaData.KEY_MSTAT37_A,
DBSportScout.MatchMetaData.KEY_MSTAT37_B,
DBSportScout.MatchMetaData.KEY_MSTAT38_A,
DBSportScout.MatchMetaData.KEY_MSTAT38_B,
DBSportScout.MatchMetaData.KEY_MSTAT39_A,
DBSportScout.MatchMetaData.KEY_MSTAT39_B,
DBSportScout.MatchMetaData.KEY_MSTAT40_A,
DBSportScout.MatchMetaData.KEY_MSTAT40_B };
String[] selectionArgs = { selectionmatchid };
Cursor c = db.fetch(DBSportScout.MatchMetaData.DATABASE_TABLE_MATCH,
columns, DBSportScout.MatchMetaData.KEY_MROWID + "=?",
selectionArgs, null, null, null, null);
c.moveToFirst();
tvfName.setText(c.getInt(c.getColumnIndexOrThrow(DBSportScout.MatchMetaData.KEY_MNAME)));
tvfTriesA.setText(c.getInt(c.getColumnIndexOrThrow(DBSportScout.MatchMetaData.KEY_MSTAT1_A)));
tvfTriesB.setText(c.getInt(c.getColumnIndexOrThrow(DBSportScout.MatchMetaData.KEY_MSTAT1_B)));
db.close();
}
}
来自DBSportScout的fetch()方法
public Cursor fetch(String table, String[] columns, String selection,
String[] args, String groupby, String having, String orderby,
String limit) { // metodo per fare la query di tutti i dati
Cursor cursor = mDb.query(table, columns, selection, args, groupby,
having, orderby, limit);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
最后这里是LogCat
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.gmail.david.corsalini.sportscout/com.gmail.david.corsalini.sportscout.MatchesRugbyPage}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.gmail.david.corsalini.sportscout.MatchDetailsFragment.populateDetails(MatchDetailsFragment.java:77)
at com.gmail.david.corsalini.sportscout.MatchDetailsFragment.onCreateView(MatchDetailsFragment.java:64)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:870)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:622)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:505)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1133)
at android.app.Activity.performStart(Activity.java:4475)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1929)
... 11 more
答案 0 :(得分:0)
进行查询时,不要在投影中要求_ID列
String[] selection= {DBSportScout.MatchMetaData.KEY_MNAME, DBSportScout.MatchMetaData.KEY_MROWID };
所以它总是为零,我想也许你需要覆盖你的适配器来返回你选择的id,或者在你的表中添加一个_id列。
答案 1 :(得分:0)
除非我开始新活动,否则我从未使用过捆绑包。我通常做的(我并不是声称它是最好的方式,但它适用于我),是定义一个公共静态变量来保存行id,然后使用它。
一个例子(只是相关的位)。
片段1(会员列表):
public static Long mRowId;
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
mRowId = id;
MemberDisplayFragment memberdisplay = new MemberDisplayFragment();
getFragmentManager().beginTransaction().replace(R.id.rightpane, memberdisplay).commit();
}
片段2(会员详细信息显示):
Cursor memberdisplay = mDbHelper.fetchMember(MemberListFragment.mRowId);
getActivity().startManagingCursor(memberdisplay);
memberdisplay.moveToFirst();
希望这有帮助!