[英]Multi-Column ListView shows zeros instead of database values
我正在 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;
}
}
我相信您的問題與 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 '\ ' String (or any object) null boolean false
您應該使用傳遞的值設置對象的變量。 所以使用:-
public Entry(float speed, double longitude, double latitude, long time){
Speed = speed;
Longitude = longitude;
Latitude = latitude;
Time = time;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.