Android Error: IllegalStateException
Android Error: IllegalStateException
我正在为 Android 开发比特币仪表板。以下片段使用输入的钱包地址显示 BTC 余额。输入地址后,它将添加到列表视图中。当列表视图中的项目被 selected 时,它会将编辑文本设置为该地址。
它还没有完成,但现在它会抛出一条消息错误,"The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread."
我目前有两个示例地址可供测试。如果我 select 一个然后另一个然后第一个再次等等。它工作正常。当我 select 一个,按下按钮,然后 select 另一个时出现错误。
public class WalletFragment extends Fragment {
ArrayList<String> savedWallets;
ArrayAdapter<String> listAdapter;
String newWalletAddress, jsonString, address, balance;
JSONObject jsonObj, data;
Double balanceDouble;
DecimalFormat df = new DecimalFormat("#.####");
private WalletListener listener;
public interface WalletListener {
void onCreateWallet(String newWalletAddress);
}
public WalletFragment() {
// Required empty public constructor
}
public static WalletFragment newInstance(ArrayList<String> wallets) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
fragment.setArguments(args);
return fragment;
}
public static WalletFragment newInstance(ArrayList<String> wallets, String json) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
args.putString("jsonString", json);
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof WalletListener) {
listener = (WalletListener) context;
}
else {
throw new ClassCastException(context.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_wallet, container, false);
ListView lv = (ListView) v.findViewById(R.id.walletListView);
df.setRoundingMode(RoundingMode.CEILING);
final EditText walletAddressEditText = (EditText) v.findViewById(R.id.walletAddressEditText);
TextView addressTV = (TextView) v.findViewById(R.id.walletAddresstextView);
TextView balanceTV = (TextView) v.findViewById(R.id.walletBalanceTextView);
savedWallets = getArguments().getStringArrayList("savedWallets");
if (savedWallets == null) {
savedWallets = new ArrayList<>();
}
savedWallets.add("198aMn6ZYAczwrE5NvNTUMyJ5qkfy4g3Hi");
savedWallets.add("1L8meqhMTRpxasdGt8DHSJfscxgHHzvPgk");
// TODO remove test addresses
jsonString = getArguments().getString("jsonString");
if (jsonString != null) {
try {
jsonString = getArguments().getString("jsonString");
jsonObj = new JSONObject(jsonString);
data = new JSONObject(jsonObj.getString("data"));
balance = data.getString("balance");
balanceDouble = Double.parseDouble(balance);
address = data.getString("address");
String walletAddressText = getResources().getString(R.string.wallet_address, address);
addressTV.setText(walletAddressText);
String walletBalanceText = getResources().getString(R.string.wallet_balance, df.format(balanceDouble));
balanceTV.setText(walletBalanceText);
// TODO add viewing for other wallet data at some point
} catch (Exception e) {
Log.d("TickerException", e.toString());
}
}
listAdapter = new ArrayAdapter<>(getActivity(), R.layout.main_list_rows, savedWallets);
lv.setAdapter(listAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String address = savedWallets.get(position);
Log.d("wallet", "Selected: " + address);
walletAddressEditText.setText(address);
}
});
Button button = (Button) v.findViewById(R.id.createWalletButton);
View.OnClickListener ocl = new View.OnClickListener() {
@Override
public void onClick(View view) {
newWalletAddress = walletAddressEditText.getText().toString();
if (walletAddressEntryStructuralValidation(newWalletAddress)) {
if (newWalletAddress != null) {
listener.onCreateWallet(newWalletAddress);
}
else {
Toast.makeText(getActivity(), "newWalletAddress is null", Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(getActivity(), "Please enter a valid wallet address (length is currently " + newWalletAddress.length() + ").", Toast.LENGTH_SHORT).show();
}
}
};
// TODO check if wallet is already on list
button.setOnClickListener(ocl);
return v;
}
public boolean walletAddressEntryStructuralValidation(String address) {
return ((address.length() > 25) &&
(address.length() < 36) && (
(address.substring(0,1).equals("1") ||
(address.substring(0,1).equals("3")))));
}
// Wallet addresses are 26-35 alphanumeric characters and begin with 1 or 3
}
我相信这是所有相关代码,但如果有人需要请求其他源代码,我会密切关注此线程。
该消息表示适配器的内容(您在 getItem 中看到的项目顺序)已更改,但未调用 notifyDataSetChanged 或类似函数。更改适配器内容中的项目时(在本例中为 savedWallets 数组列表),您必须调用其中一个函数。
注意:如果您一次添加多个对象,则只需调用一次即可,毕竟 added/removed。如果你正在改变一个对象而不是adding/removing它,你不需要调用它,但调用它可能是进行重绘的最简单方法。
我正在为 Android 开发比特币仪表板。以下片段使用输入的钱包地址显示 BTC 余额。输入地址后,它将添加到列表视图中。当列表视图中的项目被 selected 时,它会将编辑文本设置为该地址。
它还没有完成,但现在它会抛出一条消息错误,"The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread."
我目前有两个示例地址可供测试。如果我 select 一个然后另一个然后第一个再次等等。它工作正常。当我 select 一个,按下按钮,然后 select 另一个时出现错误。
public class WalletFragment extends Fragment {
ArrayList<String> savedWallets;
ArrayAdapter<String> listAdapter;
String newWalletAddress, jsonString, address, balance;
JSONObject jsonObj, data;
Double balanceDouble;
DecimalFormat df = new DecimalFormat("#.####");
private WalletListener listener;
public interface WalletListener {
void onCreateWallet(String newWalletAddress);
}
public WalletFragment() {
// Required empty public constructor
}
public static WalletFragment newInstance(ArrayList<String> wallets) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
fragment.setArguments(args);
return fragment;
}
public static WalletFragment newInstance(ArrayList<String> wallets, String json) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
args.putString("jsonString", json);
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof WalletListener) {
listener = (WalletListener) context;
}
else {
throw new ClassCastException(context.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_wallet, container, false);
ListView lv = (ListView) v.findViewById(R.id.walletListView);
df.setRoundingMode(RoundingMode.CEILING);
final EditText walletAddressEditText = (EditText) v.findViewById(R.id.walletAddressEditText);
TextView addressTV = (TextView) v.findViewById(R.id.walletAddresstextView);
TextView balanceTV = (TextView) v.findViewById(R.id.walletBalanceTextView);
savedWallets = getArguments().getStringArrayList("savedWallets");
if (savedWallets == null) {
savedWallets = new ArrayList<>();
}
savedWallets.add("198aMn6ZYAczwrE5NvNTUMyJ5qkfy4g3Hi");
savedWallets.add("1L8meqhMTRpxasdGt8DHSJfscxgHHzvPgk");
// TODO remove test addresses
jsonString = getArguments().getString("jsonString");
if (jsonString != null) {
try {
jsonString = getArguments().getString("jsonString");
jsonObj = new JSONObject(jsonString);
data = new JSONObject(jsonObj.getString("data"));
balance = data.getString("balance");
balanceDouble = Double.parseDouble(balance);
address = data.getString("address");
String walletAddressText = getResources().getString(R.string.wallet_address, address);
addressTV.setText(walletAddressText);
String walletBalanceText = getResources().getString(R.string.wallet_balance, df.format(balanceDouble));
balanceTV.setText(walletBalanceText);
// TODO add viewing for other wallet data at some point
} catch (Exception e) {
Log.d("TickerException", e.toString());
}
}
listAdapter = new ArrayAdapter<>(getActivity(), R.layout.main_list_rows, savedWallets);
lv.setAdapter(listAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String address = savedWallets.get(position);
Log.d("wallet", "Selected: " + address);
walletAddressEditText.setText(address);
}
});
Button button = (Button) v.findViewById(R.id.createWalletButton);
View.OnClickListener ocl = new View.OnClickListener() {
@Override
public void onClick(View view) {
newWalletAddress = walletAddressEditText.getText().toString();
if (walletAddressEntryStructuralValidation(newWalletAddress)) {
if (newWalletAddress != null) {
listener.onCreateWallet(newWalletAddress);
}
else {
Toast.makeText(getActivity(), "newWalletAddress is null", Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(getActivity(), "Please enter a valid wallet address (length is currently " + newWalletAddress.length() + ").", Toast.LENGTH_SHORT).show();
}
}
};
// TODO check if wallet is already on list
button.setOnClickListener(ocl);
return v;
}
public boolean walletAddressEntryStructuralValidation(String address) {
return ((address.length() > 25) &&
(address.length() < 36) && (
(address.substring(0,1).equals("1") ||
(address.substring(0,1).equals("3")))));
}
// Wallet addresses are 26-35 alphanumeric characters and begin with 1 or 3
}
我相信这是所有相关代码,但如果有人需要请求其他源代码,我会密切关注此线程。
该消息表示适配器的内容(您在 getItem 中看到的项目顺序)已更改,但未调用 notifyDataSetChanged 或类似函数。更改适配器内容中的项目时(在本例中为 savedWallets 数组列表),您必须调用其中一个函数。
注意:如果您一次添加多个对象,则只需调用一次即可,毕竟 added/removed。如果你正在改变一个对象而不是adding/removing它,你不需要调用它,但调用它可能是进行重绘的最简单方法。