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它,你不需要调用它,但调用它可能是进行重绘的最简单方法。