【问题标题】:Android Error: IllegalStateExceptionAndroid 错误:IllegalStateException
【发布时间】:2016-12-11 04:41:42
【问题描述】:

我正在为 Android 开发比特币仪表板。以下片段使用输入的钱包地址以 BTC 显示余额。输入地址后,它将添加到列表视图中。当列表视图中的一个项目被选中时,它会将编辑文本设置为该地址。

它还没有完成,但现在它会抛出错误消息,“适配器的内容已更改,但 ListView 没有收到通知。确保您的适配器的内容没有从后台修改线程,但只能来自 UI 线程。”

我目前有两个示例地址用于测试。如果我选择一个然后另一个然后第一个再等等。它工作正常。当我选择一个,按下按钮,然后选择另一个时出现错误。

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

}

我相信这是所有相关代码,但如果有人需要请求其他源,我会密切关注这个线程。

【问题讨论】:

    标签: java android fragment bitcoin illegalstateexception


    【解决方案1】:

    该消息意味着适配器的内容(您在 getItem 中看到的项目顺序)已更改,但未调用 notifyDataSetChanged 或类似函数。更改适配器内容中的项目(在本例中为 savedWallets 数组列表)时,您必须调用其中一个函数。

    注意:如果您一次添加多个对象,则只需在添加/删除所有对象后调用它一次。如果您正在改变一个对象但不添加/删除它,则不需要调用它,但调用它可能是进行重绘的最简单方法。

    【讨论】:

    • 我无意更改数据集的内容,但我正在将新的钱包地址条目添加到列表中;也许这在我不知情的情况下开始工作。我是否正确理解抛出错误是因为钱包地址字符串的 ArrayList 发生了变化,还是其他原因?
    • 是的,抛出错误是因为 savedWallets 数组不再包含相同顺序的相同项目。您可以将内容添加到此列表中,但您必须在下次重绘之前调用 notifyDataSetChanged。
    • 我想我已经解决了这个问题,但还有一个更简单的问题:我应该在哪里调用这个方法?我认为它应该放在已发布片段的 onCreateView 中,但您有更具体的位置吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2013-01-26
    相关资源
    最近更新 更多