簡體   English   中英

已解決:java.lang.IllegalStateException:創建自定義適配器時,系統服務在 onCreate() 之前不可用於活動

[英]SOLVED: java.lang.IllegalStateException: System services not available to Activities before onCreate() when creating custom-adapter

我收到一個錯誤,上面寫着“java.lang.IllegalStateException:系統服務在 onCreate() 之前不可用於活動”,盡管我所做的每個操作都是在 onCreate() 之后。

我有一個有 4 個按鈕的自定義適配器。 當單擊其中一個按鈕時,它最終會調用 updateList() 函數,該函數應該使用新的詳細信息更新列表。

這是代碼: MainActivity.java

public class MainActivity extends Activity {
    static int accountsCount = 0;
    static FileWorker fileWorker;

    static File directory;
    ListView ledgerListView;
    TextView noAccountsTextView;
    TextView accountHierarchy;
    EditText accountName;
    EditText accountLimit;

    AlertDialog.Builder accountDialogBuilderChild;
    AlertDialog accountDialogChild;

    static ArrayList<AccountsView> ledgerList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        boolean introDone = preferences.getBoolean("intro_done", false);
        boolean howToDone = preferences.getBoolean("howto_done", false);
        boolean prefFilesCreated = preferences.getBoolean("files_created", false);

       if(!introDone || !howToDone) {
            Intent introActivity = new Intent(this, IntroActivity.class);
            startActivity(introActivity);
        }

        noAccountsTextView = findViewById(R.id.noAccountsTextView);
        ledgerListView = findViewById(R.id.mainListView);

        fileWorker = new FileWorker();
        directory = getFilesDir();

        if(!prefFilesCreated) {
            boolean filesCreated = fileWorker.createFiles(directory);
            if(filesCreated) {
                SharedPreferences.Editor prefEditor = preferences.edit();
                prefEditor.putBoolean("files_created", true);
                prefEditor.apply();
            }
        }
        accountsCount = fileWorker.countAccounts(directory);
        setMainActivityView();
    }

    public void addChildAccountDialog(Context context, int pos) {
        String hierarchy = ledgerList.get(pos).getAccountName();
        String renewalType = ledgerList.get(pos).getRenewalType();
        accountDialogBuilderChild = new AlertDialog.Builder(context);
        accountDialogBuilderChild.setTitle(R.string.add_child_account_dialog_title);
        accountDialogBuilderChild.setPositiveButton("Ok",
                (dialogInterface, i) -> addChildAccount(hierarchy, renewalType));
        accountDialogBuilderChild.setNegativeButton("Cancel",
                (dialogInterface, i) -> dialogInterface.cancel());
        accountDialogBuilderChild.setView(R.layout.dialog_add_child_account);
        accountDialogChild = accountDialogBuilderChild.create();
        accountDialogChild.show();

        accountHierarchy = accountDialogChild.findViewById(R.id.accountHierarchyValueTV);
        accountHierarchy.setText(hierarchy);
        accountName = accountDialogChild.findViewById(R.id.accountNameDialogET);
        accountLimit = accountDialogChild.findViewById(R.id.accountLimitDialogET);
    }

    private void addChildAccount(String hierarchy, String renewalType) {
        String accName = hierarchy.concat(formatAccountName(accountName
                .getText().toString()));
        double accLimit = Double.parseDouble(accountLimit.getText().toString());
        fileWorker.addChildAccount(directory,
                accName,
                renewalType,
                accLimit);
        setMainActivityView();
    }

    private void setMainActivityView() {
        accountsCount = fileWorker.countAccounts(directory);
        if(accountsCount <= 0) {
            ledgerListView.setVisibility(View.GONE);
            noAccountsTextView.setVisibility(View.VISIBLE);
        } else {
            updateList();
            ledgerListView.setVisibility(View.VISIBLE);
            noAccountsTextView.setVisibility(View.GONE);
        }
    }

    public void updateList() {
        fileWorker.sortAccounts(directory);
        ledgerList = fileWorker.getAccountsList(directory);
        AccountsViewAdapter ledgerAdapter = new
                AccountsViewAdapter(this, ledgerList);
        ledgerListView.setAdapter(ledgerAdapter);
    }

    public String formatAccountName(String accName) {
        accName = accName.trim().toLowerCase();
        accName = accName.replace(' ', '_');
        accName = accName.replace('/', '_');
        if(accName.charAt(0) != '/') {
            accName = "/".concat(accName);
        }
        return accName;
    }

    public void onBackPressed() {
        new AlertDialog.Builder(this)
                .setTitle("Exit")
                .setMessage("Are you sure?")
                .setPositiveButton("Yes", (dialog, which) -> this.finishAffinity())
                .setNegativeButton("No", null)
                .show();
    }
}

這是 cutomAdapter 代碼:

public class AccountsViewAdapter extends ArrayAdapter<AccountsView> {

    TextView accountName;
    TextView renewalType;
    TextView limitValue;
    TextView balanceValue;

    Button buttonAddAccount;
    Button buttonEditAccount;
    Button buttonIncreaseBalance;
    Button buttonDecreaseBalance;

    MainActivity mainActivity;

    public AccountsViewAdapter(Context context, ArrayList<AccountsView> arrayList) {
        super(context, 0, arrayList);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View currentItemView  = convertView;

        if(currentItemView == null) {
            currentItemView = LayoutInflater.from(getContext())
                    .inflate(R.layout.listview_row, parent, false);
        }

        AccountsView currentAccount = getItem(position);

        assert currentAccount != null;

        accountName = currentItemView.findViewById(R.id.accountNameValueTextView);
        renewalType = currentItemView.findViewById(R.id.textViewRenewalTypeValue);
        limitValue = currentItemView.findViewById(R.id.limitValueTextView);
        balanceValue = currentItemView.findViewById(R.id.balanceValueTextView);

        buttonAddAccount = currentItemView.findViewById(R.id.addAccountButton);
        buttonEditAccount = currentItemView.findViewById(R.id.editAccountButton);
        buttonIncreaseBalance = currentItemView.findViewById(R.id.increaseBalanceButton);
        buttonDecreaseBalance = currentItemView.findViewById(R.id.decreaseBalanceButton);

        accountName.setText(currentAccount.getAccountName());
        renewalType.setText(currentAccount.getRenewalType());
        limitValue.setText(currentAccount.getAmountLimit());
        balanceValue.setText(currentAccount.getBalanceValue());

        mainActivity = new MainActivity();

        buttonAddAccount.setOnClickListener(v -> {
            mainActivity.addChildAccountDialog(buttonAddAccount.getContext(), position);
        });
        return currentItemView;
    }
}

據我了解,當我單擊“buttonAddAccount”按鈕時會發生錯誤。 我嘗試用 MainActivity.this 替換 MainActivity 中的上下文,但這沒有幫助。

這是錯誤日志:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.biotstoiq.seshat, PID: 18232
    java.lang.IllegalStateException: System services not available to Activities before onCreate()
        at android.app.Activity.getSystemService(Activity.java:6715)
        at android.view.LayoutInflater.from(LayoutInflater.java:299)
        at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:216)
        at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:210)
        at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:196)
        at org.biotstoiq.seshat.AccountsViewAdapter.<init>(AccountsViewAdapter.java:28)
        at org.biotstoiq.seshat.MainActivity.updateList(MainActivity.java:179)
        at org.biotstoiq.seshat.MainActivity.setMainActivityView(MainActivity.java:170)
        at org.biotstoiq.seshat.MainActivity.addChildAccount(MainActivity.java:161)
        at org.biotstoiq.seshat.MainActivity.lambda$addChildAccountDialog$2$org-biotstoiq-seshat-MainActivity(MainActivity.java:140)
        at org.biotstoiq.seshat.MainActivity$$ExternalSyntheticLambda2.onClick(Unknown Source:6)
        at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:201)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:230)
        at android.app.ActivityThread.main(ActivityThread.java:7875)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
I/Process: Sending signal. PID: 18232 SIG: 9

如果需要更多信息,請告訴我。 我只在這里發布了相關的代碼。 fileWorker 代碼不在此處,因為我認為此處不需要它。 如果這也需要,請隨時詢問。

編輯:

我按照@GabeSechan 所說的做了幾件事來解決了這個問題。

  1. 使用 notifyDataSetChanged 而不是創建適配器的新實例。
  2. 使用 clear() 和 addAll() 作為列表而不是創建一個新實例。
  3. 通過使用界面而不是我以前所做的任何事情。

謝謝你。

1)永遠不要用new ActivityClass實例化一個new ActivityClass 那沒有正確初始化它。 只有 Android 框架才能正確初始化 Activity,而您可以通過 Intent 來執行此操作。

2)即使你可以這樣初始化一個Activity,也是錯誤的。 您不想在新實例上調用該函數,而是想在您正在運行的實例上調用它。

3)無論如何,您不應該有任何視圖或適配器類需要特定的活動。 您應該使用將處理程序傳遞到適配器的接口。 這種方法更容易測試,也更容易正確。 即使您的代碼有效,也幾乎不可能進行單元測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM