英文:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论