我无法将微调器的选定项目放入我的sqlite数据库。当我单击按钮时,我的应用程序会自动关闭。
// Get sample data from the database and display them in the spinner
spinner1=(Spinner)findViewById(R.id.spinner);
ArrayList <String> list=datahelper.getAllProvinces();
ArrayAdapter <String> adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list);
spinner1.setAdapter(adapter);
ok_button=findViewById ( R.id.ok_button );
ok_button.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
Ok_button_onClick ( v );
}
} );
}
private void Ok_button_onClick(View v) {
spinner db = new spinner ( getApplicationContext () );
String firstspin= (String) spinner1.getItemAtPosition ( spinner1.getSelectedItemPosition () );
db.insertLabel ( firstspin );
Toast.makeText ( Main2Activity.this,"Selected Item" + firstspin, Toast.LENGTH_SHORT).show ();
我所得到的。。
D/AndroidRuntime:关闭VM E/AndroidRuntime: FATAL EXCEPTION: main Process:Ok_button_onClick, PID: 14079android.os.NullPointerException:尝试在android.os.SQLite的空对象引用上调用虚拟方法'intandler.dispatchSandler.java:95SelectedItemPotion()'。Main2Active.andler.java:751(Main2Aooper.loop)在ooper.java:154SQLite. Main2Aandroid.app.0美元(Main2Ahread.main)在hread.java:6077SQLite. Main2Active$java.lang.reflect.点击(2A Mainctivity.java:49)在android.view.View.perform点击(View.java:5610)在android.view.查看$PerformClick.run(View.java:22265)在android.os.Handler.handle回调(Hcom.example.newlogin)在java.lang.Handroid.widget.消息(Hpinner.get)在com.example.newlogin.loginctivity.java:64(Lcom.example.newlogin.login)在ctivity.accessActivityTctivity.java:24(ActivityTcom.example.newlogin.login)在1.onM(本机方法)在com. android. interal. os. ZygoteInit. main(ZygoteInit. java: 866)
根据答案使用ArrayList并不是最好的方法。
例如,您从列表中选择ProvinceX,然后将该值插入另一个表中,然后说ProvinceX将其名称更改为ProvinceY,然后您必须将ProvinceX更新为ProvinceY,无论它在其他表中的任何位置使用。没有那么难,但效率低,而且没有标准化(即数据重复)。
对于SQLite,除了使用不带ROWID定义的特殊表之外,所有表都有一个特殊的、通常隐藏的列,称为ROWID。它包含一个整数(最多64位有符号,因此可能包含9223372036854775807行(如果使用负值,则为两倍))。
rowid列(通常为别名(见下文))有一些优点。它可以被视为主索引(优于主索引)。搜索rowid或其别名的速度更快。
rowid表的数据存储为B-Tree结构,每个表行包含一个条目,使用rowid值作为键。这意味着通过rowid检索或排序记录是快速的。搜索具有特定rowid的记录或具有rowid的所有记录在指定范围内的速度大约是通过指定任何其他PRIMARY KEY或索引值进行的类似搜索的两倍。
用于存储rowid的存储空间将小于String的a,因此在检索数据时可以缓冲更多行。
通常,一个表会有一个专门使用整数主键的rowid别名(例如INT主键不会创建rowid的别名)。如果检查答案,您可以看到_id列(即BaseColumns._id)使用了整数主键。
因此,使用ArrayList可能效率低下,因为后续从数据库访问数据的唯一方法需要对该字符串进行效率低于最优的搜索。
如果要创建一个包含rowid(通常是其别名)的成员变量(字段)的省对象,并使用ArrayList作为微调器的源,那么使用该值可以提高效率(存储的数据越少,访问数据的速度越快,缓冲的数据越多)。
如果该值是存储在相关表中的值,则在省表中将ProvinceX更改为ProvinceY将导致该值始终发生更改。所以只需更新1。
因此,下面的工作示例包括一个微调器和使用ArrayList的按钮(也包括省级)。
正如您所经历的那样,使用Android SQLite SDK/API,您可以将数据放入游标中,正如本节标题所示,有用于列表视图和微调器的游标适配器。在我看来,使用这些工具更容易,而且它们有一些优点。它们有返回_id(应该是rowid列的别名)的方法,如果该列特别命名为_id(因此为常量BaseColumns._id),这对游标适配器很重要。如果没有这样的列,游标适配器将崩溃。如果列不是rowid列的别名,则结果不可预测。
因此,您可能希望考虑以下具有3个微调器和按钮(原始ArrayList适配器、ArrayList Aapter和CursorAdapter)的示例/演示。
所有三个输出结果到日志。
public class Province {
private long provinceId;
private String provinceName;
public Province(long id, String name) {
this.provinceId = id;
this.provinceName = name;
}
public Province(String name) {
this(-1,name);
}
public Province() {
}
public long getProvinceId() {
return provinceId;
}
public void setProvinceId(long provinceId) {
this.provinceId = provinceId;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
@Override
public String toString() {
return this.provinceName; // NOTE overridden to avoid using Custom adapter
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK">
</Button>
<Spinner
android:id="@+id/spinner2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok2_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK2 (Province ArrayList)">
</Button>
<Spinner
android:id="@+id/spinner3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok3_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK3 (Cursor)">
</Button>
</LinearLayout>
原始答案中的数据库助手根据添加了两个附加方法
//<<<<<<<<<< ADDITIONAL FOR ArrayList<Province> adapter
public ArrayList<Province> getAllProvicesAsProvinceObjects() {
ArrayList<Province> rv = new ArrayList<>();
Cursor csr = mDB.query(TABLENAME_PROVINCE,null,null,null,null,null,COL_PROVINCE_NAME);
while (csr.moveToNext()) {
rv.add(
new Province(
csr.getLong(csr.getColumnIndex(COL_PROVINCE_ID)),
csr.getString(csr.getColumnIndex(COL_PROVINCE_NAME))
)
);
}
csr.close(); //<<<<<<<<<< should always close cursors when done with them
return rv;
}
//<<<<<<<<<< ADDITIONAL FOR Cursor adapter
public Cursor getAllProvincesAsCursor() {
return mDB.query(TABLENAME_PROVINCE,null,null,null,null,null,null);
}
这是代码的三大部分。
值得注意的管理??????方法,检索最新数据,构建微调器(一次),并管理(通过在最后的onResume方法中调用)更新列表(告诉适配器数据已更改)。
public class MainActivity extends AppCompatActivity {
DatabaseHelper datahelper;
Spinner spinner1,
spinner2, //<<<<<<<<<<ADDITONAL For ArrayList<Province> adapter
spinner3 //<<<<<<<<<<ADDITIONAL for Cursor adapter
;
Button ok_button,
ok2_button, //<<<<<<<<<<ADDITIONAL For ArrayList<Province> adapter
ok3_button //<<<<<<<<<<ADDITIONAL for Cursor adapter
;
ArrayAdapter<String> adapter; //<<<<<<<<<< declares the adapter at class level
ArrayList<String> list; //<<<<<<<<<< declares at the class level
ArrayAdapter<Province> adapter2; //<<<<<<<<<<ADDITIONAL For ArrayList<Province> adapter
ArrayList<Province> list2; //<<<<<<<<<< ADDITIONAL For ArrayList<Province> adapter
SimpleCursorAdapter adapter3; //<<<<<<<<<<ADDITIONAL for Cursor adapter
Cursor mCsr; //<<<<<<<<<<ADDITIONAL for Cursor adapter
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datahelper = new DatabaseHelper(this);
loadDataForDemo(); //<<<<<<<<<< load some data for the demo
spinner1=(Spinner)findViewById(R.id.spinner);
spinner2 =(Spinner) findViewById(R.id.spinner2); //<<<<<<<<<< For ArrayList<Province> adapter
spinner3 = (Spinner) findViewById(R.id.spinner3); //<<<<<<<<<<ADDITIONAL for Cursor adapter
list=datahelper.getAllProvinces(); //<<<<<<<<<< CHANGED to use already decalred
adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list); // <<<<<<<<< CHANGED to use already decalred
spinner1.setAdapter(adapter);
ok_button=findViewById ( R.id.ok_button );
ok_button.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
Ok_button_onClick (v);
}
} );
manageSpinner2(); //<<<<<<<<<< For ArrayList<Province> adapter
ok2_button = findViewById(R.id.ok2_button);
ok2_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Ok_button2_onClick(v);
}
});
manageSpinner3(); //<<<<<<<<<<ADDITIONAL for Cursor adapter
ok3_button = findViewById(R.id.ok3_button);
ok3_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Ok_button3_onClick(v);
}
});
}
//<<<<<<<<<< For ArrayList<Province> adapter >>>>>>>>>>
private void manageSpinner2() {
list2 = datahelper.getAllProvicesAsProvinceObjects();
if (adapter2 == null) {
adapter2 = new ArrayAdapter<>(this,R.layout.spinner_layout,R.id.text,list2);
spinner2.setAdapter(adapter2);
} else {
// Note this applies any changed data (updates, insert, deletes)
adapter2.clear();
adapter2.addAll(list2);
adapter2.notifyDataSetChanged();
}
}
//<<<<<<<<<<ADDITIONAL for Cursor adapter >>>>>>>>>>
private void manageSpinner3() {
mCsr = datahelper.getAllProvincesAsCursor();
if (adapter3 == null) {
adapter3 = new SimpleCursorAdapter(
this,
R.layout.spinner_layout,mCsr,
// Note following arrays should have matching number of elements
new String[]{DatabaseHelper.COL_PROVINCE_NAME}, // columns to get data from
new int[]{R.id.text}, // view id's (TextViews) into which data goes
// Note SimpleCursorAdapter quite flexible as layout can have multiple column/view matchings
0
);
spinner3.setAdapter(adapter3);
} else {
adapter3.swapCursor(mCsr);
}
}
private void Ok_button_onClick(View v) {
String value_via_position = list.get(spinner1.getSelectedItemPosition());
String value_from_selected_item = (String) spinner1.getSelectedItem();
Log.d("SELECTED","Selected item is " + value_via_position + " according to position.");
Log.d("SELECTED","Selected item is " + value_from_selected_item + " as per the selected item method");
long id_of_province1 = datahelper.getProvinceIdFromName(value_via_position);
long id_of_province2 = datahelper.getProvinceIdFromName(value_from_selected_item);
Log.d ("SELECTED","ID (via position) is " + String.valueOf(id_of_province1) + " ID (via selected item) is " + String.valueOf(id_of_province2));
}
private void loadDataForDemo() {
// Only load provinces if none exist
if (DatabaseUtils.queryNumEntries(datahelper.getWritableDatabase(),DatabaseHelper.TABLENAME_PROVINCE) > 0) return;
String[] provinces_to_load = new String[]{
"Hereington",
"Nothereington",
"Nowherington",
"Somewhereington",
"Overthereington",
"Inthehaystackington",
"Noweheretobefoundington",
"Atsomeplaceington",
"Zeroington",
"Beforetheotherplacington"
};
for (String province: provinces_to_load) {
datahelper.addProvince(province);
}
}
//<<<<<<<<<< For OK2 button
private void Ok_button2_onClick(View v) {
Province thisProvince = (Province) spinner2.getSelectedItem();
long id = ((Province) spinner2.getSelectedItem()).getProvinceId();
//spinner2.getSelectedItemId()
String name = ((Province) spinner2.getSelectedItem()).getProvinceName();
Log.d("SELECTED2",
"You selected Province:-" +
" ID=" + String.valueOf(thisProvince.getProvinceId()) +
" Name=" + thisProvince.getProvinceName());
}
private void Ok_button3_onClick(View v) {
long id = spinner3.getSelectedItemId(); // Cursor Adapter knows the id
String name = mCsr.getString(mCsr.getColumnIndex(DatabaseHelper.COL_PROVINCE_NAME));
Log.d("SELECTED3","You clicked ID=" + String.valueOf(id) + " Name="+name);
}
@Override
protected void onResume() {
super.onResume();
manageSpinner2(); //<<<<<<<<<< will apply changed data when returning to the activity
manageSpinner3(); //<<<<<<<<<<< likewise for Cursor adapter
}
}
您的问题在于列表的范围和spinner1变量。也就是说,作用域不允许访问它们,因此它们是空的。
这两个变量都是在活动的onCreate方法中声明和实例化的,因此仅适用于该活动。
尽管您在onCreate方法中设置了按钮的onClickListener,但单击按钮时,onCreate方法将在您有机会单击按钮之前完成,并且变量将不可用。
您需要做的是在更高的(类级别)范围内声明您需要访问的变量。然后您可以在类中访问它们。
也就是说,不要使用:-
protected void onCreate(Bundle savedInstanceState) {
..........
spinner1=(Spinner)findViewById(R.id.spinner);
ArrayList <String> list=datahelper.getAllProvinces();
ArrayAdapter <String> adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list); // included as you might well want to use this
..........
}
你可以:-
public class Main2Activity extends AppCompatActivity {
.......... // may be lines here
Spinner spinner1;
Button ok_button; //<<<<<<<< included as you may want to access this as well
ArrayAdapter<String> adapter; //<<<<<<<<<< declares the adapter at class level
ArrayList<String> list; //<<<<<<<<<< declares at the class level
@Override
protected void onCreate(Bundle savedInstanceState) {
..........
spinner1=(Spinner)findViewById(R.id.spinner);
list=datahelper.getAllProvinces();
adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list);
..........
}
现在你可以使用:-
private void Ok_button_onClick(View v) {
//spinner db = new spinner ( getApplicationContext () ); //<<<<<<<<<< A new spinner? Why? Probably not hence commented out, you you mean new Database Helper (see demo below)
String firstspin= (String) spinner1.getItemAtPosition ( spinner1.getSelectedItemPosition () );
//db.insertLabel ( firstspin ); //<<<<<<<<<<commented out re above
Toast.makeText ( Main2Activity.this,"Selected Item" + firstspin, Toast.LENGTH_SHORT).show (); //could this on it's own (see demo)
以下是一个工作示例,基于问题中提供的代码。
但是,它不是在单击时插入一行(根据注释,这可能会失败),而是根据所选名称获取rowid(该行唯一的数字,因此是标识特定行的一种方法)。注意:要做到这一点,基础表中的列是使用UNIQUE定义的,因此没有两个省份可以是相同的。
loadDataForDemo
,只是为了加载一些用于演示的数据
:-
public class MainActivity extends AppCompatActivity {
DatabaseHelper datahelper;
Spinner spinner1;
Button ok_button;
ArrayAdapter<String> adapter; //<<<<<<<<<< declares the adapter at class level
ArrayList<String> list; //<<<<<<<<<< declares at the class level
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datahelper = new DatabaseHelper(this);
loadDataForDemo(); //<<<<<<<<<< load some data for the demo
spinner1=(Spinner)findViewById(R.id.spinner);
list=datahelper.getAllProvinces(); //<<<<<<<<<< CHANGED to use already declared
adapter=new ArrayAdapter<String>(this, R.layout.spinner_layout, R.id.text, list); // <<<<<<<<< CHANGED to use already declared
spinner1.setAdapter(adapter);
ok_button=findViewById ( R.id.ok_button );
ok_button.setOnClickListener ( new View.OnClickListener () {
@Override
public void onClick(View v) {
Ok_button_onClick (v);
}
} );
}
private void Ok_button_onClick(View v) {
// <<<<<<<<< shows 2 ways of getting the value from the spinner >>>>>>>>>
String value_via_position = list.get(spinner1.getSelectedItemPosition());
String value_from_selected_item = (String) spinner1.getSelectedItem();
Log.d("SELECTED","Selected item is " + value_via_position + " according to position.");
Log.d("SELECTED","Selected item is " + value_from_selected_item + " as per the selected item method");
long id_of_province1 = datahelper.getProvinceIdFromName(value_via_position);
long id_of_province2 = datahelper.getProvinceIdFromName(value_from_selected_item);
Log.d ("SELECTED","ID (via position) is " + String.valueOf(id_of_province1) + " ID (via selected item) is " + String.valueOf(id_of_province2));
}
private void loadDataForDemo() {
// Only load provinces if none exist
if (DatabaseUtils.queryNumEntries(datahelper.getWritableDatabase(),DatabaseHelper.TABLENAME_PROVINCE) > 0) return;
String[] provinces_to_load = new String[]{
"Hereington",
"Nothereington",
"Nowherington",
"Somewhereington",
"Overthereington",
"Inthehaystackington",
"Noweheretobefoundington",
"Atsomeplaceington",
"Zeroington",
"Beforetheotherplacington"
};
for (String province: provinces_to_load) {
datahelper.addProvince(province);
}
}
}
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TABLENAME_PROVINCE = "province";
public static final String COL_PROVINCE_ID = BaseColumns._ID; // use stock id column name
public static final String COL_PROVINCE_NAME = "province";
SQLiteDatabase mDB;
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLENAME_PROVINCE + "(" +
COL_PROVINCE_ID + " INTEGER PRIMARY KEY," +
COL_PROVINCE_NAME + " TEXT UNIQUE" +
")"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addProvince(String provinceName) {
ContentValues cv = new ContentValues();
cv.put(COL_PROVINCE_NAME,provinceName);
return mDB.insert(TABLENAME_PROVINCE,null,cv);
}
public ArrayList<String> getAllProvinces() {
ArrayList<String> rv = new ArrayList<>();
Cursor csr = mDB.query(TABLENAME_PROVINCE,null,null,null,null,null,COL_PROVINCE_NAME);
while (csr.moveToNext()) {
rv.add(csr.getString(csr.getColumnIndex(COL_PROVINCE_NAME)));
}
csr.close(); //<<<<<<<<<< should always close cursors when done with them
return rv;
}
public long getProvinceIdFromName(String name) {
long rv = -1; //default value to indicate not found (just in case)
String whereclause = COL_PROVINCE_NAME + "=?";
String[] wherearguments = new String[]{name};
Cursor csr = mDB.query(TABLENAME_PROVINCE,null,whereclause,wherearguments,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getLong(csr.getColumnIndex(COL_PROVINCE_ID));
}
csr.close(); //<<<<<<<<<< should always close cursors when done with them
return rv;
}
}
:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>
<Button
android:id="@+id/ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK">
</Button>
</LinearLayout>
该应用程序看起来像:-
选择微调器后(高亮显示的项目就是所选的项目):-
日志中的结果输出为:-
2019-05-15 11:07:39.300 D/SELECTED: Selected item is Noweheretobefoundington according to position.
2019-05-15 11:07:39.300 D/SELECTED: Selected item is Noweheretobefoundington as per the selected item method
2019-05-15 11:07:39.302 D/SELECTED: ID (via position) is 7 ID (via selected item) is 7
问题内容: 我创建了一个名为functioncalling.php的页面,其中包含两个按钮 Submit 和 Insert 。作为PHP的初学者,我想测试单击按钮时执行的功能。我希望输出出现在同一页面上。因此,我创建了两个功能,每个按钮一个。functioncalling.php的源代码如下: 这里的问题是单击任何按钮后都没有输出。 我到底哪里出问题了? 问题答案: 是的,您在这里需要Ajax。请
问题内容: 我正在尝试编写Django应用程序,而我却被困在单击按钮时如何调用视图函数。 在我的模板中,我有一个如下所示的链接按钮,单击该按钮会将您带到另一个网页: 单击按钮时,我还想调用Django视图函数(以及重定向到目标网站)。查看功能使数据库中的值增加,该值存储了单击按钮的次数。 该是到外部网站(如链接 www.google.com )。现在,单击该按钮时,它将打开一个新窗口,该窗口将您带
上述代码来自网站,但是尽管尝试了多次尝试,我仍无法单击此按钮。我该怎么办? 如何使用c# selenium点击按钮?以上对我不起作用。
如何在无限次或动态地单击按钮时添加新的?或者简单地说,如何执行添加更多按钮的功能? 我在Javafx中尝试过,但它只是在列表中添加了两个按钮。 但我必须动态添加,直到用户想要添加/按下上一个按钮
编辑:底部的解决方案 这是一个跳棋游戏。单击一个按钮后,它等待单击第二个按钮与之交换。然而,有时你可能不想移动那个按钮,但一旦你点击了它,就没有回头路了,因为我无法禁用它。 在这里的其他帖子中,我看到人们使用 这只是使它在第一次单击后不可见。 这什么都干不了。 这也没什么用。编辑:所有这些方法都用true和false进行了尝试。 私有无效交换(){ 但你也需要 这样它就重新启用了它,或者其他什么,