自定义CursorAdapter不会显示数据

时间:2012-05-05 21:36:42

标签: android cursor android-listview android-cursoradapter

我已实施自定义CursorAdapter。此适配器从Cursor获取数据并将其中的大部分存入ListViewListView中的一个字段需要来自不同表的数据,因此我需要再次查询数据库以在视图中设置该部分。我的ListView似乎正在工作,就像之前我在数据库中没有数据一样,它正确显示我的空标记"no data in the db"。现在数据库中有数据,ListView没有显示任何内容!这是我的自定义适配器:

    public class ScheduleAdapter extends CursorAdapter {

    private LayoutInflater mInflater;
    private int mHomeAway, mOppFK, mLocation, mWhen, mOutcome, mType, mPlayed;
    private String teamName;

    public ScheduleAdapter(Context context, Cursor c) {
        super(context, c);
        // TODO Auto-generated constructor stub

        mHomeAway = c.getColumnIndex(ScoreMasterDB.KEY_SCHHOMEAWAY);
        mOppFK = c.getColumnIndex(ScoreMasterDB.KEY_SCHOPPFK);
        mLocation = c.getColumnIndex(ScoreMasterDB.KEY_SCHLOCATION);
        mWhen = c.getColumnIndex(ScoreMasterDB.KEY_SCHWHEN);
        mOutcome = c.getColumnIndex(ScoreMasterDB.KEY_SCHOUTCOME);
        mType = c.getColumnIndex(ScoreMasterDB.KEY_SCHTYPE);
        mPlayed = c.getColumnIndex(ScoreMasterDB.KEY_SCHPLAYED);

        mInflater = LayoutInflater.from(context);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        // TODO Auto-generated method stub
        return mInflater.inflate(R.layout.schedule_main_list, parent);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // TODO Auto-generated method stub

        TextView homeAway = (TextView) view.findViewById(R.id.tvVsAt);
        TextView oppName = (TextView) view.findViewById(R.id.tvScheduleListOpponent);
        TextView location = (TextView) view.findViewById(R.id.tvScheduleListLocation);
        TextView outcomeWhen = (TextView) view.findViewById(R.id.tvScheduleDateTimeResult);
        TextView gameType = (TextView) view.findViewById(R.id.tvScheduleType);

        ScoreMasterDB dbInfo = new ScoreMasterDB(context);
        try {
            dbInfo.open();
            teamName = dbInfo.getTeamName(cursor.getInt(mOppFK));
            dbInfo.close();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        homeAway.setText(cursor.getString(mHomeAway));
        oppName.setText(teamName);
        location.setText(cursor.getString(mLocation));

        //set game time or outcome
        if(cursor.getInt(mPlayed) == 0){
            outcomeWhen.setText(cursor.getString(mWhen));

            //set text style for outcome
            if(cursor.getInt(mOutcome) == 1){
                outcomeWhen.setTextAppearance(context, R.style.greenWinText);
            }
        }

        gameType.setText(cursor.getString(mType));

    }
}

以下是我对此适配器的调用:

// get schedule cursor
            scheduleInfo = dbInfo.getScheduleCursor(teamID, seasonID);
            startManagingCursor(scheduleInfo);

            ScheduleAdapter scheduleAdapter = new ScheduleAdapter(ScheduleMain.this, scheduleInfo);
            setListAdapter(scheduleAdapter);

编辑: 调用自定义适配器的活动应该显示团队的日程安排。它通过首先显示一个选择团队的对话框,然后显示另一个选择适当季节的对话框来实现。然后,它使用匹配的teamID和seasonID向数据库查询计划。自定义适配器的原因是日程安排会将对手列为整数外键,因此我需要查询适配器中的数据库以获取对手的相应团队名称。

这是活动(相当多的代码)

    package com.scoremaster.pro;

import android.app.Dialog;
import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class ScheduleMain extends ListActivity implements OnItemClickListener,
        OnClickListener, OnItemLongClickListener {

    Dialog selectTeam, selectSeason, newSeason;
    Cursor teamInfo, seasons, scheduleInfo;
    ScoreMasterDB dbInfo;
    ListView diaList, diaSeason;
    int teamID, seasonID;
    String teamNameG;
    Button addNewSeason;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.schedule_main);

        selectTeam = new Dialog(ScheduleMain.this);
        selectTeam.setContentView(R.layout.schedule_main_dialog);
        selectTeam.setTitle("Select Team");

        dbInfo = new ScoreMasterDB(this);
        try {
            dbInfo.open();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        teamInfo = dbInfo.getTeamsCursor();
        startManagingCursor(teamInfo);

        if (teamInfo.getCount() == 0) {
            Intent createTeamIntent = new Intent(
                    "com.scoremaster.pro.CREATETEAM");
            createTeamIntent.putExtra("fromSchedule", true);
            startActivity(createTeamIntent);
        }

        String[] columns = { ScoreMasterDB.KEY_TEAMNAME };
        int[] to = { R.id.tvTeamSelectList };

        //Bundle scheduleBundle = getIntent().getExtras();
        //int whatToDo = scheduleBundle.getInt(")

        diaList = (ListView) selectTeam.findViewById(R.id.lvScheduleDialog);
        SimpleCursorAdapter teamListAdapter = new SimpleCursorAdapter(
                ScheduleMain.this, R.layout.team_select_list, teamInfo,
                columns, to);
        diaList.setAdapter(teamListAdapter);
        diaList.setOnItemClickListener(this);
        selectTeam.show();

    }

    // listview onClick events
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        // TODO Auto-generated method stub
        switch (parent.getId()) {
        case R.id.lvScheduleDialog:
            selectTeam.dismiss();
            teamInfo.moveToPosition(position);

            // set data on ScheduleMain
            TextView teamName = (TextView) findViewById(R.id.tvScheduleTeam);
            TextView teamAbbrev = (TextView) findViewById(R.id.tvScheduleAbbrev);
            TextView teamLevel = (TextView) findViewById(R.id.tvScheduleLevel);
            LinearLayout layTeam = (LinearLayout) findViewById(R.id.layScheduleTeam);
            Button bAddSchedule = (Button) findViewById(R.id.bAddGame);

            teamNameG = teamInfo.getString(1);

            teamName.setText(teamInfo.getString(1));
            teamAbbrev.setText(teamInfo.getString(2));
            teamLevel.setText(teamInfo.getString(3));
            bAddSchedule.setText("Add Game to Schedule");
            bAddSchedule.setClickable(true);

            teamID = teamInfo.getInt(0);

            // set button if no team
            if (teamInfo.getCount() == 0) {

            }

            // set listeners for bAddGame and laySheduleTeam
            bAddSchedule.setOnClickListener(this);
            layTeam.setOnClickListener(this);

            // get season information
            selectSeason = new Dialog(ScheduleMain.this);
            selectSeason.setContentView(R.layout.schedule_season_dialog);
            selectSeason.setTitle("Select Season");
            seasons = dbInfo.getSeasonsCursor(teamID);
            startManagingCursor(seasons);

            String[] columns = { ScoreMasterDB.KEY_SEANAME };
            int[] to = { R.id.tvTeamSelectList };

            // set select season dialog listview elements
            diaSeason = (ListView) selectSeason
                    .findViewById(R.id.lvSeasonDialog);
            SimpleCursorAdapter seasonListAdapter = new SimpleCursorAdapter(
                    ScheduleMain.this, R.layout.team_select_list, seasons,
                    columns, to);
            diaSeason.setAdapter(seasonListAdapter);
            diaSeason.setOnItemClickListener(this);
            diaSeason.setOnItemLongClickListener(this);

            // set add button listenter
            Button addSeason = (Button) selectSeason
                    .findViewById(R.id.bAddSeason);
            addSeason.setOnClickListener(this);

            // show dialog
            selectSeason.show();
            break;
        case R.id.lvSeasonDialog:
            // get seasonID
            selectSeason.dismiss();
            seasons.moveToPosition(position);
            seasonID = seasons.getInt(0);

            // get schedule cursor
            scheduleInfo = dbInfo.getScheduleCursor(teamID, seasonID);
            startManagingCursor(scheduleInfo);
            //scheduleInfo.moveToFirst();

            //String[] columns1 = {ScoreMasterDB.KEY_SEANAME};
            //int[] to1 = {R.id.tvScheduleAddVsAt};
            //SimpleCursorAdapter scheduleAdapter = new SimpleCursorAdapter(ScheduleMain.this, R.layout.schedule_main_list, seasons, columns1, to1);
            ScheduleAdapter scheduleAdapter = new ScheduleAdapter(ScheduleMain.this, scheduleInfo);
            setListAdapter(scheduleAdapter);
            break;

        }

    }

    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case R.id.bAddSeason:
            selectSeason.dismiss();
            newSeason = new Dialog(ScheduleMain.this);
            newSeason.setContentView(R.layout.schedule_new_season);
            newSeason.setTitle("New Season");

            TextView teamName = (TextView) newSeason
                    .findViewById(R.id.tvNewSeasonTeamName);
            teamName.setText("Create new season for the " + teamNameG);

            addNewSeason = (Button) newSeason
                    .findViewById(R.id.bSubmitNewSeason);
            addNewSeason.setOnClickListener(this);
            newSeason.show();
            break;
        case R.id.bSubmitNewSeason:
            TextView seasonName = (TextView) newSeason
                    .findViewById(R.id.etNewSeasonName);
            String submitSeason = seasonName.getText().toString();
            if (submitSeason.equalsIgnoreCase("")) {
                Toast.makeText(ScheduleMain.this, "Please enter a season name",
                        Toast.LENGTH_SHORT).show();
            } else {
                try {
                    dbInfo.insertSeason(teamID, submitSeason);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    Intent intent = getIntent();
                    finish();
                    startActivity(intent);

                }
            }

            break;
        case R.id.bAddGame:
            Intent addGame = new Intent("com.scoremaster.pro.ADDGAME");
            addGame.putExtra("teamID", teamID);
            addGame.putExtra("seasonID", seasonID);
            startActivity(addGame);

            break;
        case R.id.layScheduleTeam:
            selectTeam.show();
            break;
        }

    }

    public boolean onItemLongClick(AdapterView<?> parent, View view,
            int position, long id) {
        // TODO Auto-generated method stub
        if (parent.getId() == R.id.lvSeasonDialog) {
            seasons.moveToPosition(position);
            int rowID = seasons.getInt(0);
            dbInfo.removeSeason(rowID);
            selectSeason.dismiss();
            Intent intent = getIntent();
            finish();
            startActivity(intent);
            return true;

        } else {
            return false;

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
    }

}

这是DB类中的getScheduleCursor()方法

    public Cursor getScheduleCursor(int teamID, int seasonID){
    String[] columnsSch = {KEY_ROWID, KEY_SCHHOMEAWAY, KEY_SCHOPPFK, KEY_SCHLOCATION,  KEY_SCHWHEN, KEY_SCHOUTCOME, KEY_SCHTYPE, KEY_SCHPLAYED}; 
    Cursor c = scoreMasterDB.query(DB_SCHEDULE_TABLE, columnsSch, KEY_SCHTEAMFK + "=" + teamID + " AND " + KEY_SCHSEASON + "=" + seasonID, null, null, null, null); 

    return c;
}

1 个答案:

答案 0 :(得分:1)

ScheduleAdapter中,在对视图进行充气时,请使用未附加到根视图的inflate()版本:

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    // TODO Auto-generated method stub
    return mInflater.inflate(R.layout.schedule_main_list, parent, false);
}

另请注意,如果在原始游标(包括或替换teamName)中包含mOppFK而不是在绑定视图时创建与数据库的新连接以获取它,那会更好,因为您正在建立新连接并查询数据库中添加到ListView的每个项目。

编辑:您可以改进的事项:

A)当您需要将其传递给OnItemClickListener时,请使用匿名类型而不是让您的活动实现setOnItemClickListener(以及其他接口):

diaList.setOnItemClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });

B)要执行JOIN(并避免在适配器中打开新连接),请使用SQLiteQueryBuilder构建查询表达式:

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("foo LEFT OUTER JOIN bar ON (foo.id = bar.foo_id)")

Cursor cursor = qb.query(...);

C)不确定您在这里尝试做什么:

Intent intent = getIntent();
finish();
startActivity(intent);

您想重新开始活动吗?为什么不再打开第一个对话框?

D)以这种方式创建新Intent让我感觉更舒服:

Intent createTeamIntent = new Intent(this, CREATETEAM.class));

如果您在侦听器中,则不能使用this作为上下文传递(因为它不引用该活动)。在这种情况下,您可以在活动中声明atributte:

Context context;

OnCreate中初始化:

this.context = this;

然后只需拨打context即可随时使用。