java.lang.IllegalStateException:创建自定义适配器时,系统服务在 onCreate() 之前对活动不可用
Posted
技术标签:
【中文标题】java.lang.IllegalStateException:创建自定义适配器时,系统服务在 onCreate() 之前对活动不可用【英文标题】:java.lang.IllegalStateException: System services not available to Activities before onCreate() when creating custom-adapter 【发布时间】:2021-12-21 20:22:17 【问题描述】:我收到一条错误消息:
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 代码不在此处,因为我认为此处不需要它。
【问题讨论】:
这个答案可能会对您有所帮助***.com/a/32133034/17333641 @MuhammadRiaz 我试过这个。不起作用。谢谢你试图帮助我。 【参考方案1】:永远不要使用new ActivityClass
实例化 Activity。这没有正确初始化它。只有 Android 框架可以正确初始化 Activity,而您可以通过 Intent 来完成。
即使你可以像这样初始化一个 Activity,那也是错误的。您不想在新实例上调用该函数,而是想在正在运行的实例上调用它。
无论如何,您不应该有任何视图或适配器类需要特定的 Activity。您应该使用将处理程序传递给适配器的接口。这种方法更容易测试,也更容易正确。即使您的代码有效,也几乎不可能进行单元测试。
【讨论】:
以上是关于java.lang.IllegalStateException:创建自定义适配器时,系统服务在 onCreate() 之前对活动不可用的主要内容,如果未能解决你的问题,请参考以下文章