简体   繁体   中英

NullPointerException accessing Room Database from Utility Class (non-Activity)

I have been trying to create an utility class for my Android app, so instead of each Activity calling Room database - all of the operations would be performed in that one 'Utility' class and requested from each activity whenever and wherever needed.

I have tried to establish connection with database in the same way as within SettingsActivity (in onCreate) as well as within the corresponding class responsible for the required operation) - without any luck.

Firstly, the code for retrieving number of fares saved within the Room database from within the Activity class.

SettingsActivity.java

public void deletingFares(View view) {

// start of attempt of getting the value from QueriesUtility class

    QueriesUtility qu = new QueriesUtility();
    String quString = qu.returnNumberOfFares();

    Toast.makeText(SettingsActivity.this, 
    "Data from Queries Utilities class: (number of fares):" 
                    + quString, Toast.LENGTH_LONG).show();
// end

Code for QueriesUtility.java class:

public class QueriesUtility extends AppCompatActivity {

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

    // FARES DB
    // establishing connection with db
    mFareDAO = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "db-fares")
            .build()
            .getFareDAO();
}

public String returnNumberOfFares() {

    CalcNumberOfFares ss = new CalcNumberOfFares();
    ss.execute("");

    return numberOfFares;
}

String numberOfFares = "d0";
private FareDAO mFareDAO;
/**
 * CALCULATING NUMBER OF FARES
 */
private class CalcNumberOfFares extends AsyncTask<String, Integer, String> {

    // #1 - This is run in a background thread
    @Override
    protected String doInBackground(String... params) {
        // get the string from params, which is an array
        String myString = params[0];

        // FARES DB
        // establishing connection with db
        mFareDAO = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "db-fares")
                .build()
                .getFareDAO();

        List<Fare> fares = mFareDAO.getAllFares();

        myString = String.valueOf(fares.size());
        numberOfFares = myString;

        return myString;
    }


    // #2 - This runs in UI when background thread finishes
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        numberOfFares = result;

// todo


    }
}

/**
 *
 * END
 */
}

As you can tell - I've tried to establish connection with database in both ways in an act of desperation ;) (within onCreate as well as within CalcNumberOfFares). Is 'onCreate' ignored - as class is a non-Activity class?

The following is the log with the error:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #4
              Process: com.example.android.taxidriverassistant, PID: 26280
              java.lang.RuntimeException: An error occurred while executing doInBackground()
                  at android.os.AsyncTask$3.done(AsyncTask.java:353)
                  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
                  at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:271)
                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
                  at java.lang.Thread.run(Thread.java:764)
               Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
                  at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:119)
                  at com.example.android.taxidriverassistant.QueriesUtility$CalcNumberOfFares.doInBackground(QueriesUtility.java:57)
                  at com.example.android.taxidriverassistant.QueriesUtility$CalcNumberOfFares.doInBackground(QueriesUtility.java:47)
                  at android.os.AsyncTask$2.call(AsyncTask.java:333)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
                  at java.lang.Thread.run(Thread.java:764) 
I/Process: Sending signal. PID: 26280 SIG: 9
Application terminated. 

When calls to Room DB are performed within the Activity's class - everything works as it should.

This is how connection with Room database is established within SettingsActivity.java:

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

    // FARES DB
    // establishing connection with db
    mFareDAO = Room.databaseBuilder(this, AppDatabase.class, "db-fares")
            .build()
            .getFareDAO();

And code for DeletingFares (which works within the SettingsActivity.java class):

    /**
 * DELETING FARES CLASS
 */
private class DeletingFares extends AsyncTask<String, Integer, String> {

    // #1 - This is run in a background thread
    @Override
    protected String doInBackground(String... params) {
        // get the string from params, which is an array
        String myString = params[0];

        List<Fare> fares = mFareDAO.getAllFares();

        myString = String.valueOf(fares.size());
        numberOfFares = myString;
        // value of myString is send over to onPostExecute and used in the end to make an Alert

        // if there are no fares - no further action should take place
        if (fares.size() > 0) {
            for (int i = 0; i < fares.size(); i++) {
                Fare ff = fares.get(i);
                mFareDAO.delete(ff);
            }
        }
        return myString;
    }


    // #2 - This runs in UI when background thread finishes
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        // invoking method which displays the alert at the end
        alertAfterDeletingFares();


    }
}

As I understand the concept behind the NullPointerException - the reference to the object within QueriesUtility class (but requested from SettingsActivity class) does not exist as there is no connection to the database, hence to object is being referenced and returns null (is that correct?).

I would really appreciate if someone could point me into the right direction. Thank you so much!

You need to pass context to AsyncTask instead of using getApplicationContext() .

Refer getApplicationContext in AsyncTask class?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM