Исключение нулевого указателя после перемещения некоторого кода в пользовательский класс приложения

#java #android

#java #Android

Вопрос:

Получение NullPointerException после того, как я переместил часть кода в отдельный пользовательский класс приложения, называемый YambaApplication . Это приложение отправляет сообщения в службу с поддержкой Twitter. Я проверил код 3 раза и очистил проект 5 раз:

Исключение:

06-16 14:08:22.723: E/AndroidRuntime(392): Вызвано: java.lang.Исключение NullPointerException 06-16 14:08:22.723: E/AndroidRuntime(392): на com.user.yamba.StatusActivity$PostToTwitter.doInBackground(StatusActivity.java:70)

YambaApplication.java (здесь мы инициализируем и возвращаем объект twitter):

 package com.user.yamba;

import winterwell.jtwitter.Twitter;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;

    public class YambaApplication extends Application implements
            OnSharedPreferenceChangeListener {

        private static final String TAG = YambaApplication.class.getSimpleName();
        public Twitter twitter;
        private SharedPreferences prefs;

        @Override
        public void onCreate() {
            super.onCreate();
            this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
            this.prefs.registerOnSharedPreferenceChangeListener(this);
            Log.i(TAG, "onCreated");
        }

        @Override
        public void onTerminate() {
            super.onTerminate();
            Log.i(TAG, "onTerminated");
        }

        @Override
        public synchronized void onSharedPreferenceChanged(
                SharedPreferences sharedPreferences, String key) {
            this.twitter = null;

        }

        public synchronized Twitter getTwitter() {
            if (this.twitter == null) {
                String username, password, apiRoot;
                username = this.prefs.getString("username", "");
                password = this.prefs.getString("password", "");
                apiRoot = this.prefs.getString("apiRoot",
                        "http://yamba.marakana.com/api");
                if (!TextUtils.isEmpty(username) amp;amp; !TextUtils.isEmpty(password)
                        amp;amp; !TextUtils.isEmpty(apiRoot)) {
                    this.twitter = new Twitter(username, password);
                    this.twitter.setAPIRootUrl(apiRoot);
                }
            }
            return this.twitter;
        }

    }
  

StatusActivity.java (первое действие, которое пользователь видит с EditText помощью кнопки и обновления. Большая часть кода из YambaApplication class находилась внутри этого класса.):

 package com.user.yamba;

import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class StatusActivity extends Activity implements OnClickListener,
        TextWatcher {
    private static final String TAG = "StatusActivity";
    EditText editTextStatusUpdate;
    Button buttonStatusUpdate;
    TextView textViewCharacterCounter;
    //SharedPreferences prefs;

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

        // Find views
        editTextStatusUpdate = (EditText) findViewById(R.id.editStatus);
        buttonStatusUpdate = (Button) findViewById(R.id.buttonUpdate);
        buttonStatusUpdate.setOnClickListener(this);

        textViewCharacterCounter = (TextView) findViewById(R.id.editTextUpdateStatusCounter);
        textViewCharacterCounter.setText(Integer.toString(140));
        textViewCharacterCounter.setTextColor(Color.GREEN);
        editTextStatusUpdate.addTextChangedListener(this);

        //prefs = PreferenceManager.getDefaultSharedPreferences(this);
        //prefs.registerOnSharedPreferenceChangeListener(this);

        // Initialize twitter
        // twitter = new Twitter("student", "password");
        // twitter.setAPIRootUrl("http://yamba.marakana.com/api");

    }

    @Override
    public void onClick(View v) {
        String statusUpdate = editTextStatusUpdate.getText().toString();
        new PostToTwitter().execute(statusUpdate);
        Log.d(TAG, "onClicked");
    }

    // Async class to post of twitter
    class PostToTwitter extends AsyncTask<String, Integer, String> {

        // Async post status to twitter
        @Override
        protected String doInBackground(String... params) {
            try {
                YambaApplication yamba = ((YambaApplication) getApplication());
                Twitter.Status status = yamba.getTwitter().updateStatus(params[0]); // EXCEPTION FIRED HERE
                return status.text;
            } catch (TwitterException e) {
                Log.e(TAG, "Failed to connect to twitter service");
                return "Failed to post";
            }

        }

        // Called when there's status to be updated
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            // Not used
        }

        // Called once async task completed
        @Override
        protected void onPostExecute(String result) {
            Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG)
                    .show();
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        // Not in use

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // Not in use

    }

    // Update characters counter after text
    // is changed(entered or deleted)
    @Override
    public void afterTextChanged(Editable statusText) {
        int count = 140 - statusText.length();
        textViewCharacterCounter.setText(Integer.toString(count));
        textViewCharacterCounter.setTextColor(Color.GREEN);
        if (count < 10) {
            textViewCharacterCounter.setTextColor(Color.YELLOW);
        }
        if (count < 0) {
            textViewCharacterCounter.setTextColor(Color.RED);
        }
    }

    // When user taps on the menu hardware button inflate
    // the menu resource
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    // Determine what item user tapped on the menu
    // and start the item's activity
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.itemPrefs:
            startActivity(new Intent(this, PrefsActivity.class));
            break;
        }
        return true;
    }

//  private Twitter getTwitter() {
//      if (twitter == null) {
//          String username, password, apiRoot;
//          username = prefs.getString("username", "");
//          password = prefs.getString("password", "");
//          apiRoot = prefs.getString("apiRoot",
//                  "http://yamba.marakana.com/api");
//
//          // Connect to twitter
//          twitter = new Twitter(username, password);
//          twitter.setAPIRootUrl(apiRoot);
//      }
//      return twitter;
//  }

//  @Override
//  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
//          String key) {
//      // invalidate twitter
//      twitter = null;
//
//  }
}
  

Манифест (добавлена эта строка в тег приложения в манифесте):

 android:name=".YambaApplication"
  

Комментарии:

1. Перед использованием проверьте значение params[] , yamba и yamba.getTwitter() как not null . Знание того, какой из них равен нулю, поможет вам предпринять соответствующие действия. Лучше изменить (по крайней мере, завершить отладку) Twitter.Status status = yamba.getTwitter().updateStatus(params[0]); на Twitter? twitter = yamba.getTwitter(); после проверки на ненулевое значение Twitter.Status status = twitter.updateStatus(params[0]);

Ответ №1:

Первое, что я увидел, это новые проверки на наличие текста в имени пользователя и пароле. Возможно, попробуйте выполнить отладку, если они оба установлены правильно, и если объект Twitter возвращается из приложения или просто null из-за этих проверок.

Ответ №2:

Null — это потому, что в YambaApplication вы проверяете:

 if (!TextUtils.isEmpty(username) amp;amp; !TextUtils.isEmpty(password)
    amp;amp; !TextUtils.isEmpty(apiRoot)) {
    ...
}
  

Если какое-либо поле пустое, вы получаете twiter == null .