2014-06-15 2 views
1

데이터베이스의 데이터가 포함 된 2 개의 스피너가 포함 된 앱을 만들려고합니다. 버튼을 누르면 새로운 의도가 만들어져 2 개의 스피너가 표시됩니다. 문제는 새 스레드에서 DB 쿼리를 만들어야하고 응용 프로그램을 실행할 때 null 포인터 예외가 발생합니다 (내 이해가 간다면 DB 데이터를 저장하는 배열이 아직 채워지지 않음). 내 질문은 어떻게 DB에서 쿼리를 만들 때까지 회 전자 생성을 지연시킬 수 있습니까? 아래 내 구현의 샘플 코드 : 나는 스피너를 만들 의도는 DB 쿼리를 만드는 클래스에 전화를 걸 : 나는를 만들기 위해 새 스레드를 생성스레드가 실행 완료되었는지 확인하는 방법 Android Studio

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 

그리고 클래스를 DB 쿼리 :

public getDBdata() 
{ 
    Thread thread = new Thread(new Runnable(){ 
     @Override 
     public void run() { 
      DBconn(); //make a DB query 
     } 
    }); 
    thread.start(); 
} 
public String[][] getData() 
{ 
    return data; 
} 

답변

2

가장 쉬운 방법은 AsyncTask을 사용하는 것입니다. AsyncTask의 기본 아이디어는 차례대로 진행되는 세 단계로 작업을 분할하는 것입니다. 각 단계는 별도의 스레드에서 실행됩니다. 마지막 하나는 회 전자를 만들 수있는 메인 (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 
    } 
} 
+0

건배는 내가 찾고 있던 것이 었습니다! – relysis

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를 사용하여 작업을 수행해야합니다.

관련 문제