我是Java的android应用程序的新手。该示例应用程序应让我选择我想要在ListView中使用的货币。每次我想从列表中选择一种货币时,应用程序崩溃都会收到错误消息:
Process: com.example.a5_listview, PID: 12333
java.lang.ClassCastException: androidx.appcompat.widget.AppCompatTextView cannot be cast to android.widget.CheckedTextView
at com.example.a5_listview.MainActivity$1.onItemClick(MainActivity.java:48)
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
List<WalutaNBP> waluty = new ArrayList<>();
ListView listView;
Context context;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
context = this;
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView v = (CheckedTextView) view;
boolean aktualnyWybor = v.isChecked();
WalutaNBP waluta = (WalutaNBP) listView.getItemAtPosition(position);
waluta.setWybrana(aktualnyWybor);
}
});
pobierzWaluty();
}
private void pobierzWaluty() {
progressDialog = ProgressDialog.show(context, "Pobieram waluty",
"Proszę czekać...", true);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
URL nbpEndpoint =
new URL("http://api.nbp.pl/api/exchangerates/tables/a/");
HttpURLConnection nbpConnection =
(HttpURLConnection) nbpEndpoint.openConnection();
nbpConnection.setRequestProperty("Accept", "application/json");
if(nbpConnection.getResponseCode() == 200) {
InputStreamReader is =
new InputStreamReader(nbpConnection.getInputStream());
Gson gson = new Gson();
final WalutyNBP[] walutyNBP = gson.fromJson(is, WalutyNBP[].class);
nbpConnection.disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
waluty.addAll(Arrays.asList(walutyNBP[0].getWaluty()));
Collections.sort(waluty);
ArrayAdapter<WalutaNBP> arrayAdapter =
new ArrayAdapter<WalutaNBP>(context,
android.R.layout.simple_list_item_1, waluty);
listView.setAdapter(arrayAdapter);
zaznaczWybrane();
progressDialog.dismiss();
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "Wystąpił problem z pobraniem danych",
Toast.LENGTH_LONG).show();
}
});
}
} catch(Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "Wystąpił problem z pobraniem danych",
Toast.LENGTH_LONG).show();
}
});
}
}
});
}
private void zaznaczWybrane() {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> kodyWybranychWalut = pref.getStringSet("kodyWalut", new HashSet<String>());
for(int i = 0; i < waluty.size(); i++) {
WalutaNBP waluta = waluty.get(i);
if(kodyWybranychWalut.contains(waluta.getCode())) {
waluta.setWybrana(true);
listView.setItemChecked(i, true);
}
}
}
public void zapiszWybrane(View view) {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> kodyWybranychWalut = new HashSet<>();
for(WalutaNBP waluta : waluty) {
if(waluta.isWybrana()) {
kodyWybranychWalut.add(waluta.getCode());
}
}
pref.edit().putStringSet("kodyWalut", kodyWybranychWalut).apply();
}
}
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</ListView>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:onClick="zapiszWybrane"
android:text="Zapisz"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
WalutyNBP.java
import com.google.gson.annotations.SerializedName;
public class WalutyNBP {
private String table;
private String no;
private String effectiveDate;
@SerializedName(value = "rates")
private WalutaNBP[] waluty;
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getEffectiveDate() {
return effectiveDate;
}
public void setEffectiveDate(String effectiveDate) {
this.effectiveDate = effectiveDate;
}
public WalutaNBP[] getWaluty() {
return waluty;
}
public void setWaluty(WalutaNBP[] waluty) {
this.waluty = waluty;
}
}
WalutaNBP.java
class WalutaNBP implements Comparable<WalutaNBP> {
private String currency;
private String code;
private double mid;
private transient boolean wybrana = false;
public WalutaNBP() {
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public double getMid() {
return mid;
}
public void setMid(double mid) {
this.mid = mid;
}
public boolean isWybrana() {
return wybrana;
}
public void setWybrana(boolean wybrana) {
this.wybrana = wybrana;
}
@Override
public String toString() {
return String.format("%s [%s: %.3f]", code, currency, mid);
}
@Override
public int compareTo(WalutaNBP walutaNBP) {
return code.compareTo(walutaNBP.getCode());
}
}
在日志中,我可以看到导致所有混乱的行:
CheckedTextView v = (CheckedTextView) view;
该错误的原因是什么?我已经查看了StackOverflow上的其他答案,但仍然找不到任何解决方案。也许我只是看不到明显的错误。感谢帮助。
最佳答案
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView v = (CheckedTextView) view;
boolean aktualnyWybor = v.isChecked();
WalutaNBP waluta = (WalutaNBP) listView.getItemAtPosition(position);
waluta.setWybrana(aktualnyWybor);
}
});
在这里,您可以设置点击监听器。 “视图”字段是从适配器返回的,它是TextView。这样就可以得到castexception。在这种方法中,您可以使用id和position字段。
如果要启用多选,则需要使用其他布局来构建ArrayAdapter,如下所示:
ArrayAdapter<WalutaNBP> arrayAdapter =
new ArrayAdapter<WalutaNBP>(context,
android.R.layout.simple_list_item_multiple_choice, waluty);