英文:
androidx.appcompat.widget.AppCompatTextView cannot be cast to android.widget.CheckedTextView
问题
I'm new in android apps in Java. The example app should let me choose currencies I want to have in the `ListView`. Every time I want to choose a currency from the list, the app crashes I get the error:
E/AndroidRuntime: FATAL EXCEPTION: main
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`:
```java
package com.example.a5_listview;
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<nbpCurrency> currencies = 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 isCurrentChoice = v.isChecked();
nbpCurrency currency = (nbpCurrency) listView.getItemAtPosition(position);
currency.setChosen(isCurrentChoice);
}
});
getCurrencies();
}
private void getCurrencies() {
progressDialog = ProgressDialog.show(context, "Getting currencies",
"Please wait...", 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 nbpCurrencies[] nbpCurrenciesArray = gson.fromJson(is, nbpCurrencies[].class);
nbpConnection.disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
currencies.addAll(Arrays.asList(nbpCurrenciesArray[0].getCurrencies()));
Collections.sort(currencies);
ArrayAdapter<nbpCurrency> arrayAdapter =
new ArrayAdapter<nbpCurrency>(context,
android.R.layout.simple_list_item_1, currencies);
listView.setAdapter(arrayAdapter);
selectChosen();
progressDialog.dismiss();
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "There was a problem getting the data",
Toast.LENGTH_LONG).show();
}
});
}
} catch(Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "There was a problem getting the data",
Toast.LENGTH_LONG).show();
}
});
}
}
});
}
private void selectChosen() {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> chosenCurrenciesCodes = pref.getStringSet("currenciesCodes", new HashSet<String>());
for(int i = 0; i < currencies.size(); i++) {
nbpCurrency currency = currencies.get(i);
if(chosenCurrenciesCodes.contains(currency.getCode())) {
currency.setChosen(true);
listView.setItemChecked(i, true);
}
}
}
public void saveChosen(View view) {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> chosenCurrenciesCodes = new HashSet<>();
for(nbpCurrency currency : currencies) {
if(currency.isChosen()) {
chosenCurrenciesCodes.add(currency.getCode());
}
}
pref.edit().putStringSet("currenciesCodes", chosenCurrenciesCodes).apply();
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<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="saveChosen"
android:text="Save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
nbpCurrencies.java:
package com.example.a5_listview;
import com.google.gson.annotations.SerializedName;
public class nbpCurrencies {
private String table;
private String no;
private String effectiveDate;
@SerializedName(value = "rates")
private nbpCurrency[] currencies;
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 nbpCurrency[] getCurrencies() {
return currencies;
}
public void setCurrencies(nbpCurrency[] currencies) {
this.currencies = currencies;
}
}
nbpCurrency.java:
package com.example.a5_listview;
class nbpCurrency implements Comparable<nbpCurrency> {
private String currency;
private String code
<details>
<summary>英文:</summary>
I'm new in android apps in Java. The example app should let me choose currencies I want to have in the `ListView`. Every time I want to choose a currency from the list, the app crashes I get the error:
E/AndroidRuntime: FATAL EXCEPTION: main
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`:
```java
package com.example.a5_listview;
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<nbpCurrency> currencies = 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 isCurrentChoice = v.isChecked();
nbpCurrency currency = (nbpCurrency) listView.getItemAtPosition(position);
currency.setChosen(isCurrentChoice);
}
});
getCurrencies();
}
private void getCurrencies() {
progressDialog = ProgressDialog.show(context, "Getting currencies",
"Please wait...", 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 nbpCurrencies[] nbpCurrenciesArray = gson.fromJson(is, nbpCurrencies[].class);
nbpConnection.disconnect();
runOnUiThread(new Runnable() {
@Override
public void run() {
currencies.addAll(Arrays.asList(nbpCurrenciesArray[0].getCurrencies()));
Collections.sort(currencies);
ArrayAdapter<nbpCurrency> arrayAdapter =
new ArrayAdapter<nbpCurrency>(context,
android.R.layout.simple_list_item_1, currencies);
listView.setAdapter(arrayAdapter);
selectChosen();
progressDialog.dismiss();
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "There was a problem getting the data",
Toast.LENGTH_LONG).show();
}
});
}
} catch(Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
Toast.makeText(context, "There was a problem getting the data",
Toast.LENGTH_LONG).show();
}
});
}
}
});
}
private void selectChosen() {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> chosenCurrenciesCodes = pref.getStringSet("currenciesCodes", new HashSet<String>());
for(int i = 0; i < currencies.size(); i++) {
nbpCurrency currency = currencies.get(i);
if(chosenCurrenciesCodes.contains(currency.getCode())) {
currency.setChosen(true);
listView.setItemChecked(i, true);
}
}
}
public void saveChosen(View view) {
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Set<String> chosenCurrenciesCodes = new HashSet<>();
for(nbpCurrency currency : currencies) {
if(currency.isChosen()) {
chosenCurrenciesCodes.add(currency.getCode());
}
}
pref.edit().putStringSet("currenciesCodes", chosenCurrenciesCodes).apply();
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<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="saveChosen"
android:text="Save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
nbpCurrencies.java:
package com.example.a5_listview;
import com.google.gson.annotations.SerializedName;
public class nbpCurrencies {
private String table;
private String no;
private String effectiveDate;
@SerializedName(value = "rates")
private nbpCurrency[] currencies;
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 nbpCurrency[] getCurrencies() {
return currencies;
}
public void setCurrencies(nbpCurrency[] currencies) {
this.currencies = currencies;
}
}
nbpCurrency.java:
package com.example.a5_listview;
class nbpCurrency implements Comparable<nbpCurrency> {
private String currency;
private String code;
private double mid;
private transient boolean chosen = false;
public nbpCurrency() {
}
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 isChosen() {
return chosen;
}
public void setChosen(boolean chosen) {
this.chosen = chosen;
}
@Override
public String toString() {
return String.format("%s [%s: %.3f]", code, currency, mid);
}
@Override
public int compareTo(nbpCurrency nbpCurrency) {
return code.compareTo(nbpCurrency.getCode());
}
}
In logs I can see the line causing all of mess:
CheckedTextView v = (CheckedTextView) view;
What is cause of that error? I've looked through other answers on StackOverflow but I still can't find any solution. Maybe I just don't see an obvious mistake. Thanks for help.
答案1
得分: 1
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView v = (CheckedTextView) view;
boolean isCurrentChoice = v.isChecked();
nbpCurrency currency = (nbpCurrency) listView.getItemAtPosition(position);
currency.setChosen(isCurrentChoice);
}
});
在这里你设置了一个点击监听器。view 字段是从适配器返回的,它是一个 TextView。这就是你出现 ClassCastException 的方式。在这个方法中,你还可以获取 id 和 position 字段,并且你可以使用它们。
如果你想启用多选功能,你需要使用另一个布局来构建你的 ArrayAdapter,就像这样:
ArrayAdapter<nbpCurrency> arrayAdapter =
new ArrayAdapter<nbpCurrency>(context,
android.R.layout.simple_list_item_multiple_choice, currencies);
英文:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView v = (CheckedTextView) view;
boolean isCurrentChoice = v.isChecked();
nbpCurrency currency = (nbpCurrency) listView.getItemAtPosition(position);
currency.setChosen(isCurrentChoice);
}
});
Here you set a ClickListener. The view field is returned from adapter and it is TextView. That's the way you get CastException. In this method you also get id and position fields and you can use them.
If you want to enable multi-choice, you need to build your ArrayAdapter with another layout like this:
ArrayAdapter<nbpCurrency> arrayAdapter =
new ArrayAdapter<nbpCurrency>(context,
android.R.layout.simple_list_item_multiple_choice, currencies);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论