SimpleCursorAdapter.getItemId()到detailFragment。如何传递_id?

时间:2012-05-18 12:07:18

标签: android android-fragments simplecursoradapter android-listfragment

我正在撰写FragmentActivity我有ListFragment(使用SimpleCursorAdapter), detailsFragment detailActivity (在手机处于人像状态时使用,嵌入 detailsFragment ) 当我单击列表中的一个项目时,它应该使用来自第二个游标的数​​据填充 detailFragment ,使用所选项目的_id作为selectionArgs构建。 但是,_id似乎没有通过,我在ListFragment举杯祝酒,我展示了所选项目的_id(并且它是正确的),但是在 detailsFragment _id永远不会到达(它保持等于0,发送NullPointerException)。 我在哪里误会?

编辑:我忘了说当我使用 back 按钮从detailsActivity返回时,列表为空,它说明数据库正在关闭。
Logcat消息可以在我的帖子末尾找到。

家长活动

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

2 个答案:

答案 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();

希望这有帮助!