1

I have an application that stores some data in SharedPreferences. This control data is synchronized with a server, and when the user logins in the application I retrieve it using an AsyncTask. I'm trying to store the data retrieved in SharedPreferences again, but I'm getting a java.lang.ExceptionInInitializerError.

This is the AsyncTask code:

public class RetrieveLogTask extends AsyncTask<Void, Void, Boolean> {
    private String errorMessage;

    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            String controlRow = NetworkUtilities.getData();

            if(controlRow != null){
                LogHandler.restoreControls(LoginActivity.this, controlRow);                 
                return true;                        
            }
        } catch (AuthenticationException e) {
            errorMessage = e.getMessage();
        } catch (Exception e) {
            errorMessage = e.getMessage();
        }

        return false;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        mRetrieveTask = null;

        if (success) {              
            createAccountAndFinish(true);
        } 
        else{
            Log.d("LoginActivity", errorMessage);
            askRetry();
        }
    }

    @Override
    protected void onCancelled() {
        mRetrieveTask = null;
        showProgress(false);
    }
}

And this is the function in LogHandler class causing the error:

public static void restoreControls(Context ctx, String controlRow){
    String[] controls = controlRow.split(LogHandler.FILE_COLUMN_SEPARATOR_ESCAPED);
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
    Editor editor = prefs.edit();

    editor.putString(TODService.PREFS_KEY_ARRAY_ICONTROLS, controlRow); // ERROR HERE

    editor.commit();
}

The line that causes the error is the putString call. controlRow is not null and not empty, and editor is not null.

This is the log output:

04-19 10:59:50.900: E/AndroidRuntime(16609): FATAL EXCEPTION: AsyncTask #2
04-19 10:59:50.900: E/AndroidRuntime(16609): java.lang.RuntimeException: An error occured while executing doInBackground()
04-19 10:59:50.900: E/AndroidRuntime(16609):    at android.os.AsyncTask$3.done(AsyncTask.java:278)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.lang.Thread.run(Thread.java:856)
04-19 10:59:50.900: E/AndroidRuntime(16609): Caused by: java.lang.ExceptionInInitializerError
04-19 10:59:50.900: E/AndroidRuntime(16609):    at com.timeondriver.tod.log.LogHandler.restoreControls(LogHandler.java:835)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at com.timeondriver.tod.authenticate.LoginActivity$RetrieveLogTask.doInBackground(LoginActivity.java:328)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at com.timeondriver.tod.authenticate.LoginActivity$RetrieveLogTask.doInBackground(LoginActivity.java:1)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
04-19 10:59:50.900: E/AndroidRuntime(16609):    ... 5 more
04-19 10:59:50.900: E/AndroidRuntime(16609): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-19 10:59:50.900: E/AndroidRuntime(16609):    at android.os.Handler.<init>(Handler.java:121)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at com.timeondriver.tod.TODService$1.<init>(TODService.java:513)
04-19 10:59:50.900: E/AndroidRuntime(16609):    at com.timeondriver.tod.TODService.<clinit>(TODService.java:513)
04-19 10:59:50.900: E/AndroidRuntime(16609):    ... 10 more

Anybody knows how to fix it??

Thanks!

[EDIT]

I add some code:

private void askRetry() {
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(LoginActivity.this);

    alertDialogBuilder
    .setTitle(getResources().getString(R.string.title_error_retry))
    .setMessage(getResources().getString(R.string.message_error_retry))
    .setCancelable(false)

    .setPositiveButton(getResources().getString(R.string.retry)
            ,new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,int id) {
            mRetrieveTask = new RetrieveLogTask();
            mRetrieveTask.execute((Void) null);
        }
    })

    .setNegativeButton(getResources().getString(R.string.alert_cancel)
            ,new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,int id) {
            showProgress(false);    
        }
    })
    ; // Fin alertDialogBuilder

    AlertDialog alertDialog = alertDialogBuilder.create();
    alertDialog.show();     
}

private void createAccountAndFinish(boolean logRetrieved){
    showProgress(false);

    // Create the local account.
    Account account = new Account(mPhone, ACCOUNT_TYPE);
    Bundle user_data = new Bundle();
    try{
        mAccountManager.addAccountExplicitly(account, mPassword, user_data);
    }catch(Exception e){
        e.printStackTrace();
        return;
    }

    // Set account's additional data and finish the activity.
    final Intent intent = new Intent();
    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mPhone);
    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
    intent.putExtra(AccountManager.KEY_PASSWORD, mPassword);
    intent.putExtra(AccountManager.KEY_AUTHTOKEN, mAuthToken);
    intent.putExtra(AccountManager.KEY_BOOLEAN_RESULT, true);
    LoginActivity.this.setAccountAuthenticatorResult(intent.getExtras());
    setResult(RESULT_OK, intent);        

    Intent i = new Intent(this, Main.class);
    startActivity(i);
    LoginActivity.this.finish();
}

In TODService.java:513 there's a Handler declaration:

private static Handler mHandler = new Handler(){
    ...
}

[/EDIT]

4

1 回答 1

1

ExceptionInInitializerError - 表示静态初始化程序中发生了意外异常。抛出 ExceptionInInitializerError 以指示在评估静态初始化程序或静态变量的初始化程序期间发生异常。

java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序

似乎您正在做一些事情来更新您UINon-UI thread. 即,来自后台工作线程

您必须LogHandler.restoreControls(LoginActivity.this, controlRow);onPostExecute();.

所以你编辑的课程必须看起来像

public class RetrieveLogTask extends AsyncTask<Void, Void, Boolean>
{
    private String errorMessage;

    @Override
    protected Sring doInBackground(Void... params)
    {
        String controlRow = null;
        try
        {
            controlRow = NetworkUtilities.getData();
        }
        catch ( AuthenticationException e )
        {
            errorMessage = e.getMessage();
        }
        catch ( Exception e )
        {
            errorMessage = e.getMessage();
        }
        return controlRow;
    }

    @Override
    protected void onPostExecute(final String controlRow)
    {
        mRetrieveTask = null;
        if ( controlRow != null )
        {
            LogHandler.restoreControls(LoginActivity.this, controlRow);
            createAccountAndFinish(true);
        }
        else
        {
            Log.d("LoginActivity", errorMessage);
            askRetry();
        }
    }

    @Override
    protected void onCancelled()
    {
        mRetrieveTask = null;
        showProgress(false);
    }
}
于 2013-04-19T09:26:02.370 回答