我有一个联赛列表,我想在每个条目中显示保龄球的数目。例如:

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

我想在列表中的每个联赛名称下显示每个列表中的保龄球人数。例如:

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

这是为了快速了解每个联赛。

我尝试使用以下代码完成此操作:

数据库助手

//Getting Number of Bowlers in League
    public String leagueBowlerCount(String leagueId)
    {

        SQLiteDatabase db = this.getReadableDatabase();
    String countQuery = "SELECT * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'";
    Cursor cursor = db.rawQuery(countQuery, null);

    int count = 0;
    if(null != cursor)
        if(cursor.getCount() > 0){
            cursor.moveToFirst();
            count = cursor.getInt(0);
        }
    cursor.close();


db.close();
return String.valueOf(count);
}


联赛适配器

public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView id;
        public TextView name;
        public TextView baseScore;
        public TextView basePercentage;
        public TextView bowlerCount;
        TextView timestamp;
        public TextView buttonViewOption;

        MyViewHolder(View view) {
            super(view);
            if (!(itemView instanceof AdView)) {
                id = view.findViewById( R.id.tvLeagueId);
                name = view.findViewById(R.id.tvLeagueName );
                baseScore = view.findViewById( R.id.tvBaseScore);
                basePercentage = view.findViewById(R.id.tvBaseScorePercentage);
                bowlerCount = view.findViewById(R.id.tvNumberOfBowlers);
                timestamp = view.findViewById(R.id.timestamp);
                buttonViewOption = view.findViewById(R.id.buttonViewOptions);
            }
        }
    }

    public LeagueAdapter(Context context, List<League> leaguesList) {
        this.context = context;
        this.leaguesList = leaguesList;
        mainActivity = (Activity) context;
        inflater = LayoutInflater.from(context);
    }

    public LeagueAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        AdView adview;
        MyViewHolder holder;

        if (viewType == AD_TYPE) {
            adview = new AdView(mainActivity);
            adview.setAdSize( AdSize.BANNER);

            // this is the good adview
            adview.setAdUnitId(mainActivity.getString(R.string.admob_ad_id));

            float density = mainActivity.getResources().getDisplayMetrics().density;
            int height = Math.round(AdSize.BANNER.getHeight() * density);
            AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, height);
            adview.setLayoutParams(params);

            // dont use below if testing on a device
            // follow https://developers.google.com/admob/android/quick-start?hl=en to setup testing device
            AdRequest request = new AdRequest.Builder().build();
            adview.loadAd(request);
            holder = new MyViewHolder(adview);

        }else{
            View view = inflater.inflate(R.layout.listview_league, parent, false);
            holder = new MyViewHolder(view);
        }
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        if(position % 10 != 5) {
            League league = leaguesList.get(position);
            int id = league.getId();
            String leagueId = String.valueOf(id);
            holder.id.setText(leagueId);
            holder.name.setText(league.getName());
            holder.baseScore.setText(league.getBasisScore());
            holder.basePercentage.setText(league.getBaseScorePercentage());
            holder.bowlerCount.setText(db.leagueBowlerCount(leagueId));
            holder.timestamp.setText(formatDate(league.getTimestamp()));

            holder.buttonViewOption.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                //creating a popup menu
                PopupMenu popup = new PopupMenu(context, holder.buttonViewOption);
                //inflating menu from xml resource
                popup.inflate(R.menu.league_options_menu);
                //adding click listener
                popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                 public boolean onMenuItemClick(MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.profile:
                            //Log.d("leagueId", String.valueOf(position));
                            //int leagueId = league.getId();
                            ((MainActivity) context).openDialog(true, leaguesList.get(position), position);
                            break;
                            case R.id.delete:
                                ((MainActivity) context).deleteLeague(position);
                                break;
                        }
                        return false;
                    }
                });
                //displaying the popup
                popup.show();
                }
            });
        }
    }


我已经为此纠缠了好几天,我不知道为什么这行不通。任何帮助将不胜感激。我认为可能有一种更容易实现的方式,而我尚不清楚。

在日志猫中,我看到以下消息:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String ca.vogl.r.tenpinbowlingcompanion.database.DatabaseHelper.leagueBowlerCount(java.lang.String)' on a null object reference.


如下所述,该错误似乎发生在上面列出的LeagueBowlerCount()中。

在onBindViewHolder上进行以下添加之后:db = new DatabaseHelper(mainActivity)。我看到的价值应该在哪里,但它们不正确。参见下面的图片。

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

测试联赛1(有3个保龄球,其中1个被测试广告隐藏)

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

测试联赛2(只有1个投球手)

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

测试联赛3(有3个保龄球,其中1个被测试广告隐藏)

java - 使保龄球计数显示在League RecyclerView中-LMLPHP

因此,基本上,您应该在测试联赛1中看到3,在测试联赛2中看到1,在测试联赛3中看到3

所以现在看来​​问题出在我编写的LeagueBowlercount函数上。它没有获得仅与单个联赛ID相关的计数

最佳答案

我相信您的问题是,您返回的是第一个选定的圆顶硬礼帽的ID,而不是行数。

也就是说,在检查行数大于0后,移至第一行,然后使用count = cursor.getInt(0);,它将是已提取的第一行第一列中存储的值。

尝试使用:-

public String leagueBowlerCount(String leagueId)
{
    String rv = "0";
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(Bowler.TABLE_NAME,new String[]{"count(*)"},Bowler.COLUMN_LEAGUE_ID + "=?",new String[]{leagueId},null,null,null);
    if (cursor.moveToFirst()) {
        rv = String.valueOf(cursor.getLong(0));
    }
    cursor.close();
    db.close();
    return rv;
}


这使用聚合函数计数来提取各个联赛的行数。


请注意,上面的代码是内部代码,尚未经过测试或运行,因此可能会有一些错误。


或者,您可以使用:-

public String leagueBowlerCount(String leagueId)
    {

    SQLiteDatabase db = this.getReadableDatabase();
    String countQuery = "SELECT * FROM " + Bowler.TABLE_NAME + " WHERE " + Bowler.COLUMN_LEAGUE_ID + " = '" + leagueId + "'";
    Cursor cursor = db.rawQuery(countQuery, null);

    int count = cursor.getCount();
    cursor.close();
    db.close();
    return String.valueOf(count);
}


关于您的代码:

int count = 0;
if(null != cursor)
    if(cursor.getCount() > 0){
        cursor.moveToFirst();
        count = cursor.getInt(0);
    }
cursor.close();



检查null游标是没有用的,因为从SQLiteDatabase方法(例如rawQuery)返回的Cursor永远不会为null。而是将返回一个有效的(可能为空的)游标。
另外,使用getCount方法检查游标是否有行,然后不需要使用moveToFirst,因为仅使用if (cursor.moveToFirst) {.....}就足够了,因为如果没有行,则moveToFirst方法将返回false,因为移动不能采取行动。

08-26 02:22