多列 ListView 显示零而不是数据库值

Posted

技术标签:

【中文标题】多列 ListView 显示零而不是数据库值【英文标题】:Multi-Column ListView shows zeros instead of database values 【发布时间】:2020-03-25 04:09:49 【问题描述】:

我正在 android studio 中制作一个速度计应用程序,每次用户超过保存的速度限制时,他当前的速度、经度、纬度和时间都应该存储在数据库中。然后用户将能够查看列表中的条目。我已经创建了everythinf,但是列表视图(使用适配器有 4 列)只显示零而不是数据库值。

数据库助手


package com.mortoglou.speedometer;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class DatabaseHelper extends SQLiteOpenHelper 
    public static final String DATABASE_NAME = "limits_list_final.db";
    public static final String TABLE_NAME = "limits_list";
    public static final String COL1 = "ID";
    public static final String COL2 = "SPEED";
    public static final String COL3 = "LONGITUDE";
    public static final String COL4 = "LATITUDE";
    public static final String COL5 = "TIMESTAMP";


    public DatabaseHelper(@Nullable Context context) 
        super(context, DATABASE_NAME, null, 3);
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        String createTable = "CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
                " SPEED TEXT, LONGITUDE TEXT, LATITUDE TEXT, TIMESTAMP TEXT)";
        db.execSQL(createTable);
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL("DROP TABLE IF EXISTS TABLE_NAME");
        onCreate(db);
    

    public boolean addData(float curSpeed, double longitude, double latitude, long timestamp)
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COL2, curSpeed);
        contentValues.put(COL3, longitude);
        contentValues.put(COL4, latitude);
        contentValues.put(COL5, timestamp);


        long result = db.insert(TABLE_NAME, null, contentValues);
        if (result == -1) 
            return false;
         else 
            return true;
        
    

    public Cursor getListContents()
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor data = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
        return data;
    



主要活动


'package com.mortoglou.speedometer;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.Manifest;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements LocationListener, PopUP.PopUpListener 

    private TextView textView;
    private String savedSpeedText;
    private Button updateSpeedButton;
    private Button checkLimits;

    DatabaseHelper myDB;

    public double longi;
    public int ch = 1; //choice
    public float savedSpeed;
    public static final String SHARED_PREFS = "sharedprefs";
    public static final String SAVED_SPEED = "savedspeed";

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView5);
        updateSpeedButton = (Button) findViewById(R.id.button);
        checkLimits = (Button) findViewById(R.id.button2);

        myDB = new DatabaseHelper(this);

        updateSpeedButton.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                popUp();


            
        );

        checkLimits.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                //setContentView(R.layout.speed_limits);
                Intent intent = new Intent(MainActivity.this, LimitsList.class);
                startActivity(intent);
            
        );

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) 

            int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 0;
            ActivityCompat.requestPermissions(this,
                    new String[]Manifest.permission.ACCESS_FINE_LOCATION,
                    MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        

        LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

        // this.onLocationChanged(null);
        //savedSpeed();
        loadSpeed();
        updateSpeed();
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.speed_menu, menu);
        return true;
    


    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) 

        switch (item.getItemId()) 
            case R.id.speed1:
                ch = 1; // choice 1 = m/s
                return true;
            case R.id.speed2:
                ch = 2; // choice 2 = km/h
                return true;
        
        return super.onOptionsItemSelected(item);
    


    @Override
    public void onLocationChanged(Location location) 

        TextView txt = (TextView) this.findViewById(R.id.textView2);
        float curSpeed = location.getSpeed();
        double longitude = location.getLongitude();
        double latitude = location.getLatitude();
        long timestamp = location.getTime();

        if (location == null) 
            txt.setText("NO LOCATION FOUND");
         else 
            if (curSpeed > 0) 
                if (ch == 1) 
                    txt.setText(String.format(curSpeed + "m/s"));

                 else if (ch == 2) 
                    txt.setText(String.format(curSpeed * 3.6 + "km/h"));
                
             else 
                txt.setText("-");
            
            speedLimit(curSpeed, longi, latitude, timestamp);
        


    

    public void savedSpeed() 
        SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        editor.putFloat(SAVED_SPEED, savedSpeed);
        editor.apply();

    

    public void loadSpeed() 
        SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);

        savedSpeedText = String.valueOf(sharedPreferences.getFloat(SAVED_SPEED, 0));

    

    public void updateSpeed() 
        textView.setText(savedSpeedText);

    

    public void popUp() 
        PopUP popUP = new PopUP();
        popUP.show(getSupportFragmentManager(), "pop up");
    

    public void speedLimit(float curSpeed, double longitude, double latitude, long timestamp) 
        if (curSpeed > savedSpeed) 
            Toast.makeText(this, "Ayo you goin too fast", Toast.LENGTH_SHORT).show();
            AddData(curSpeed, longi, latitude, timestamp);

        

    


    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) 

    

    @Override
    public void onProviderEnabled(String provider) 

    

    @Override
    public void onProviderDisabled(String provider) 

    

    @Override
    public void passText(float speedText) 
        savedSpeed = speedText;
        savedSpeed();
        loadSpeed();
        updateSpeed();
    

    public void AddData(float curSpeed, double longitude, double latitude, long time) 
        boolean insertData = myDB.addData(curSpeed, longitude, latitude, time);

        if (insertData == true) 
            Toast.makeText(MainActivity.this, "Successfully Entered Data!", Toast.LENGTH_LONG).show();
         else 
            Toast.makeText(MainActivity.this, "Something went wrong :(.", Toast.LENGTH_LONG).show();
        
    


(查看内容)


    package com.mortoglou.speedometer;

import android.database.Cursor;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;

public class LimitsList extends AppCompatActivity 

    DatabaseHelper myDB;
    ArrayList<Entry> entryList;
    ListView listView;
    Entry entry;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.speed_limits);

        //listView = (ListView) findViewById(R.id.limits_list);
        myDB = new DatabaseHelper(this);

        //populate an ArrayList<String> from the database and then view it
        entryList = new ArrayList<>();
        Cursor data = myDB.getListContents();
        if (data.getCount() == 0) 
            Toast.makeText(this, "There are no contents in this list!", Toast.LENGTH_LONG).show();
         else 
            int i=0;
            while(data.moveToNext())
                entry = new Entry(data.getFloat(1),data.getDouble(2),data.getDouble(3), data.getLong(4));
                entryList.add(entry);
                //System.out.println(data.getFloat(1)+" "+data.getDouble(2)+" "+data.getDouble(3), data.getLong(4));
                System.out.println(entryList.get(i).getSpeed());
                i++;
            
            LimitsAdapter adapter = new LimitsAdapter(this, R.layout.final_list_adapter, entryList);
            listView = findViewById(R.id.limits_list);
            listView.setAdapter(adapter);
        
    



进入


    package com.mortoglou.speedometer;

public class Entry 

    private float Speed;
    private double Longitude;
    private double Latitude;
    private long Time;



    public Entry(float speed, double longitude, double latitude, long time)
        speed = Speed;
        longitude = Longitude;
        latitude = Latitude;
        time = Time;
    

    public float getSpeed() 
        return Speed;
    

    public void setSpeed(float speed) 
        Speed = speed;
    

    public double getLongitude() 
        return Longitude;
    

    public void setLongitude(double longitude) 
        Longitude = longitude;
    

    public double getLatitude() 
        return Latitude;
    

    public void setLatitude(double latitude) 
        Latitude = latitude;
    

    public long getTime() 
        return Time;
    

    public void setTime(long time) 
        Time = time;
    

适配器



    package com.mortoglou.speedometer;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class LimitsAdapter extends ArrayAdapter<Entry> 

    private LayoutInflater mInflater;
    private ArrayList<Entry> entries;
    private int mViewResourceId;


    public LimitsAdapter(Context context, int textViewResourceId, ArrayList<Entry> entries) 
        super(context, textViewResourceId, entries);
        this.entries = entries;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mViewResourceId = textViewResourceId;
    

    public View getView(int position, View convertView, ViewGroup parent) 
        convertView = mInflater.inflate(mViewResourceId, null);

        Entry entry = entries.get(position);


        TextView speed = (TextView) convertView.findViewById(R.id.speed);
        TextView longitude = (TextView) convertView.findViewById(R.id.longitude);
        TextView latitude = (TextView) convertView.findViewById(R.id.latitude);
        TextView timestamp = (TextView) convertView.findViewById(R.id.timestamp);
        speed.setText(Float.toString(entry.getSpeed()));
        longitude.setText(Double.toString((entry.getLongitude())));
        latitude.setText(Double.toString((entry.getLatitude())));
        timestamp.setText(Long.toString(entry.getTime()));


        return convertView;
    



【问题讨论】:

【参考方案1】:

我相信您的问题在于 Entry 对象的构造函数。

你有:-

public Entry(float speed, double longitude, double latitude, long time)
    speed = Speed;
    longitude = Longitude;
    latitude = Latitude;
    time = Time;

它使用对象变量中保存的值设置/覆盖传递给构造函数的值,这将是变量类型的默认值(0),因为没有分配任何值。

默认值

并不总是需要赋值 字段被声明。已声明但未初始化的字段将 由编译器设置为合理的默认值。通常来说,一般来说, 此默认值将为零或空,具体取决于数据类型。依靠 然而,在这样的默认值上,通常被认为是不好的 编程风格。

下图总结了以上数据的默认值 类型。

Data Type Default Value (for fields)
byte  0
short 0
int   0
long  0L
float 0.0f
double    0.0d
char  '\u0000'
String (or any object)    null
boolean   false

Primitive Data Types

您应该使用传递的值设置对象的变量。所以使用:-

public Entry(float speed, double longitude, double latitude, long time)
    Speed = speed;
    Longitude = longitude;
    Latitude = latitude;
    Time = time;

【讨论】:

是的!这就是问题所在。非常感谢您的回答,我现在可以继续我的项目了!再次感谢!

以上是关于多列 ListView 显示零而不是数据库值的主要内容,如果未能解决你的问题,请参考以下文章

如何在prometheus + grafana中显示零而不是最后一个值

检查数据框中的记录数是不是大于零而不使用计数火花

光标数组进入 ListView 但多列

当数组值为零而不是空时,c循环停止

如何让C#中listview控件显示多行多列数据?

如何只为单元格内的某些视图提供值,同时留下一些零而不崩溃?