2016-08-14 30 views
1

我的應用程序中有另一個問題。我用下面的代碼在MainActivity從我ContactAdapter獲取用戶數據:AsyncCallback優先

private List<String> loadContactData() { 
    ContactAdapter db = new ContactAdapter(getApplicationContext()); 
    // Spinner Drop down elements 
    List<String> contacts = db.getAllContacts();   
    // Creating adapter for spinner 
    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, 
      android.R.layout.simple_spinner_item, contacts); 
    // Drop down layout style - list view with radio button 
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);   
    Log.d("SPINNER", String.valueOf(contacts)); 
    return contacts; 
} 

而且ContactAdapter:

public List<String> getAllContacts(){ 
    final List<String> contacts_id = new ArrayList<String>(); 
    final List<String> contacts_name = new ArrayList<String>(); 
    Backendless.Data.of(BackendlessUser.class).find(new AsyncCallback<BackendlessCollection<BackendlessUser>>() { 
     public void handleResponse(BackendlessCollection<BackendlessUser> users) { 
      Iterator<BackendlessUser> userIterator = users.getCurrentPage().iterator(); 
      while (userIterator.hasNext()) { 
       BackendlessUser user = userIterator.next(); 
       String user_mail = user.getEmail(); 
       String user_id = user.getUserId(); 
       contacts_name.add(user_mail); 
       contacts_id.add(user_id); 
      } 
      Log.d("getAllContacts: ", String.valueOf(contacts_name)); } 
     public void handleFault(BackendlessFault backendlessFault) { 
      System.out.println("Server reported an error - " + backendlessFault.getMessage());}}); 
    return contacts_name; 
} 

當然,我的問題是,Backendless查詢是慢......所以在我的Logcat中,我首先看到一個空的「SPINNER」,第二個「getAllContacts」與來自服務器的用戶數據。由於loadContactData()的return contacts語句也是空的。

我該如何實現getAllContacts()完成第一個獲取loadContactData()中的用戶數據?

回答

1

你的問題是find調用是異步的(這是好的,意味着在新線程上調用handleResponse())。因此,當您的return contacts_name運行時,contacts_name仍爲空,因爲您的handleResponse()中的代碼尚未運行,因爲新線程仍在等待數據庫的響應。

對數據庫的調用很慢,因爲它可能包含文件甚至網絡IO。你不應該在與視圖一起工作的主線程上執行此操作,否則應用程序將不再響應,因爲更新UI(並繪製微調器動畫)的主線程正忙於等待數據庫。通過使數據庫請求異步,您的應用保持響應,UI不會「卡住」。

爲了簡單起見,你可以做這樣的:

public class MyActivity extends AppCompatActivity { 

    private List<String> mContactIds = new ArrayList<>(); 

    private Spinner mSpinner; 

    private ProgressDialog mProgressDialog; 

    @Overrride 
    public void onCreate() { 

     this.setContentView(...); 
     this.mSpinner = ...; 

     this.showLoadingDialog(); 

     Backendless.Data.of(BackendlessUser.class).find(new AsyncCallback<BackendlessCollection<BackendlessUser>>() { 
      public void handleResponse(BackendlessCollection<BackendlessUser> users) { 

       List<String> mails = new ArrayList<>(); 
       List<String> ids = new ArrayList<>(); 
       Iterator<BackendlessUser> userIterator = users.getCurrentPage().iterator(); 
       while (userIterator.hasNext()) { 
        BackendlessUser user = userIterator.next(); 
        String mail = user.getEmail(); 
        String id = user.getUserId(); 
        mails.add(user_mail); 
        ids.add(user_id); 
       } 

       Log.d("getAllContacts: ", String.valueOf(contacts_name)); 
       applyData(mails, ids); 

      } 

      public void handleFault(BackendlessFault backendlessFault) { 
       Log.e("error: ", "Something went wrong"); 

      } 
     }); 
    } 

    private void applyData(List<String> mails, List<String> ids) { 
     Log.d("getAllContacts: ", String.valueOf(contacts_name)); 
     this.hideLoadingDialog(); 
     this.mContactIds = ids; 
     this.mSpinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mails); 

    } 

    private void showLoadingDialog() { 
     this.mLoadingDialog = new ProgressDialog(this, null, "Loading contacts...", true); 
     this.mLoadingDialog.dismiss(); 

    } 

    private void hideLoadingDialog() { 
     if(this.mLoadingDialog != null) { 
      this.mLoadingDialog().dismiss(); 

     } 
    } 

    private void showErrorDialog() { 
     this.hideLoadingDialog(); 
     new AlertDialog.Builder(this) 
      .setMessage("Something went wrong, try again") 
      .setPositiveButton("Ok", null) 
      .show(); 

    } 
} 
+0

我嘗試用註冊用戶在服務器上填充MultiSelectionSpinner。因此,我在MainActivity的onCreate中使用以下代碼:列表 contact_list = loadContactData(); String [] contact_stringArray = contact_list。toArray(new String [contact_list.size()]); spinner =(MultiSelectionSpinner)findViewById(R.id.mySpinner1); spinner.setItems(contact_stringArray); – Timitrov

+0

我添加了一些示例代碼,這應該是最小的努力解決方案。你應該顯示一個進度對話框,讓用戶在等待數據的時候發生一些事情。如果出現問題,你也應該顯示錯誤對話框 – crysxd

1

最好的選擇,這裏將是一個監聽器接口連接到ContactAdapter,使MainActivity實現連接的接口。所以當ContactAdapter完成取數據時,它會通知監聽器類,然後你可以從主活動onRecieve回調中調用loadContactData()

public void getAllContacts(MyListener listener){ 
final List<String> contacts_id = new ArrayList<String>(); 
final List<String> contacts_name = new ArrayList<String>(); 
Backendless.Data.of(BackendlessUser.class).find(new AsyncCallback<BackendlessCollection<BackendlessUser>>() { 
    public void handleResponse(BackendlessCollection<BackendlessUser> users) { 
     Iterator<BackendlessUser> userIterator = users.getCurrentPage().iterator(); 
     while (userIterator.hasNext()) { 
      BackendlessUser user = userIterator.next(); 
      String user_mail = user.getEmail(); 
      String user_id = user.getUserId(); 
      contacts_name.add(user_mail); 
      contacts_id.add(user_id); 
     } 
     Log.d("getAllContacts: ", String.valueOf(contacts_name)); } 
    public void handleFault(BackendlessFault backendlessFault) { 
     System.out.println("Server reported an error - " + backendlessFault.getMessage());}}); 
listener.done(contacts_name); 

}

和接口可能看起來像這樣

public interface MyListener { 
    void done(List<String> contactList); 
} 

然後MainActivity應該實現MyListener接口和實現方法,你可以設置微調有內部。

我相信loadContact()可重構爲類似於

private void loadContactData() { 
ContactAdapter db = new ContactAdapter(getApplicationContext()); 
// Spinner Drop down elements 
db.getAllContacts(this);   

} 

請注意,您MainActivity實現MyListener接口。即

class MainActivity ... implements MyListener { 
    @Override 
    public void done(List<String> contacts) { 
     // Creating adapter for spinner 
    ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, 
     android.R.layout.simple_spinner_item, contacts); 
// Drop down layout style - list view with radio button 
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);   
    Log.d("SPINNER", String.valueOf(contacts)); 

    } 

這應該給你一個頭,我想你應該能夠從這裏找到你的方式。也嘗試重構代碼。

+0

感謝您的麻煩!我明白哪些步驟對我的目標是必要的,但我不知道如何從MainActivity onReceive回調中調用loadContactData()...此刻我打電話給列表 contact_list = loadContactData();在onCreate中,然後我可以使用onCreate將數據提供給我的Spinner:spinner =(MultiSelectionSpinner)findViewById(R.id.mySpinner1); spinner.setItems(contact_stringArray);我希望你能再次幫助我! – Timitrov

+0

根據我對您的問題的理解,主要目標是在設置適配器和微調器值之前等待「Backendless」服務完成。我認爲'ContactAdapter'是在一個單獨的類中,這就是爲什麼我建議使用回調。 –