我正在尝试创建一个包含2个微调器的应用程序,其中包含来自数据库的数据。按下按钮时,会创建一个新意图,显示2个微调器。问题是我必须在一个新线程中创建数据库查询,当我运行应用程序时,我得到一个空指针异常(据我所知,这是因为我存储数据库数据的数组是尚未填充)。 我的问题是,如何在数据库查询完成之前延迟创建旋转器? 下面是我的实现示例代码: 我创建微调器并调用进行数据库查询的类的意图:
String [][] dbData; //the array where i store data from DB
getDBdata myData = new getDBdata(); // create a new instance of the class that queries the DB
dbData = myData.getData(); // I get the data
Log.e("My log: ", String.valueOf(dbData.length)); //and here it crashes, giving me a null pointer exception
我创建新线程以进行数据库查询的类:
public getDBdata()
{
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
DBconn(); //make a DB query
}
});
thread.start();
}
public String[][] getData()
{
return data;
}
答案 0 :(得分:2)
最简单的方法是使用AsyncTask
。 AsyncTask
的基本思想是将您的任务执行分成三个一个接一个的步骤。每个步骤都在一个单独的线程中运行。最后一个在Main(UI)中运行,您可以在其中创建您的微调器。样品:
public class DBQueryTask extends AsyncTask<Void, Void, String[][]> {
@Override
protected String[][] doInBackground(Void... params) {
DBconn();
String[][] a;
//...populating array
return a;//returning populated array
}
@Override
protected void onPostExecute(String[][] strings) {
//strings - array already populated
//this method runs on the Main thread. Therefore you can create your spinner
}
}
答案 1 :(得分:0)
如果您想等待它完成,您不需要新的主题。但如果你这样做,那么你就不需要等待它完成,而是使用回调方法
private static final int MESSAGE_DATA_RETRIEVED = 1;
private String [][] dbData; //the array where i store data from DB
private Handler mHandler;
// in onCreate or constructor depending what are you in
mHandler = new DataHandler(this);
// end of onCreate or constructor
private void getData() {
final getDBdata myData = new getDBdata(mHandler);
myData.getData();
}
private void onDataRetrieved() {
Log.e("My log: ", String.valueOf(dbData.length));
}
private static final class DataHandler extends Handler {
private final WeakReference<YourEnclosingClass> mClassReference;
DataHandler(final YourEnclosingClass instance) {
mClassReference = new WeakReference<>(instance);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == MESSAGE_DATA_RETRIEVED) {
final YourEnclosingClass instance = mClassReference.get();
if (instance != null) {
instance.onDataRetrieved();
}
}
}
}
获取数据类
private final Handler mHandler;
// calling a class a verb is bad. Should be a noun, but I haven't took a time to rename it here
public getDBdata(final final Handler handler) {
mHandler = handler;
// starting a Thread in constructor is a bad idea. I moved it to a method
}
public void getData()
{
final Thread thread = new Thread(new Runnable(){
@Override
public void run() {
DBconn(); //make a DB query
nHandler.sendEmptyMessage(MESSAGE_DATA_RETRIEVED);
}
});
thread.start();
}
多线程如何完成。
但无论如何这是一个坏主意。您必须为您的任务使用AsyncTask或CursorLoader。