从实用程序类(非活动)访问房间数据库的 NullPointerException
Posted
技术标签:
【中文标题】从实用程序类(非活动)访问房间数据库的 NullPointerException【英文标题】:NullPointerException accessing Room Database from Utility Class (non-Activity) 【发布时间】:2019-06-26 01:50:00 【问题描述】:我一直在尝试为我的 android 应用程序创建一个实用程序类,而不是每个 Activity 调用 Room 数据库 - 所有操作都将在该一个“实用程序”类中执行,并随时随地从每个 Activity 请求。
我尝试以与在 SettingsActivity 中(在 onCreate 中)以及在负责所需操作的相应类中相同的方式建立与数据库的连接 - 没有任何运气。
首先,从 Activity 类中检索保存在 Room 数据库中的票价数量的代码。
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
QueryUtility.java 类的代码:
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
*/
正如你所知道的——我绝望地尝试以两种方式建立与数据库的连接;)(在 onCreate 和 CalcNumberOfFares 中)。 'onCreate' 是否被忽略 - 因为类是非 Activity 类?
以下是出现错误的日志:
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.
当在 Activity 的类中执行对 Room DB 的调用时 - 一切正常。
这就是在 SettingsActivity.java 中与 Room 数据库建立连接的方式:
@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();
DeletingFares 的代码(在 SettingsActivity.java 类中工作):
/**
* 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();
据我了解 NullPointerException 背后的概念 - 对 QueriesUtility 类中对象的引用(但从 SettingsActivity 类请求)不存在,因为没有与数据库的连接,因此对象被引用并返回 null(是对吗?)。
如果有人能指出我正确的方向,我将不胜感激。非常感谢!
【问题讨论】:
【参考方案1】:您需要将context
传递给AsyncTask
,而不是使用getApplicationContext()
。
参考getApplicationContext in AsyncTask class?
【讨论】:
您好 Gokul,非常感谢您的回答。我只是需要澄清一下。我是在onCreate
(即使它不是活动)还是在AsyncTask
中使用上下文而不是getApplicationContext()
?它应该如下所示吗? private class CalcNumberOfFares extends AsyncTask<String, Integer, String> private Context context; public CalcNumberOfFares(Context context) this.context = context;
非常感谢您迄今为止的帮助。以上是关于从实用程序类(非活动)访问房间数据库的 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章