2015-09-20 74 views
0

我有一個應用程序,我想要使用ISBN搜索圖書並將其顯示在屏幕上。 Book對象存儲在以ISBN作爲主鍵的Realm數據庫中。如果它們不存儲在數據庫中,則它們將從服務器異步檢索(ASyncTask),然後存儲在數據庫中。Realm數據庫 - 如何構建我的Android應用程序

現在,我不熟悉Realm以及如何使用它。

在下面的代碼中,ViewBookActivityMainController是否在同一個線程上運行,因此使用相同的數據庫實例?從「靜態類」返回Realm對象會成爲問題嗎?

如何保證致電MainController.getBook()總是返回一本書?現在它的工作方式是,當調用getBook並且該書不在數據庫中時,它將返回null。

是每個使用MainController唯一方法的Activity的changelisteners嗎?如果可能的話,我希望避免在活動中使用/引用Realm,並讓它們通過MainController獲取對象。

public class RealmActivity extends Activity { 
    private Realm realm; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).build(); 
     Realm.deleteRealm(realmConfiguration); // Clean slate 
     Realm.setDefaultConfiguration(realmConfiguration); // Make this Realm the default 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
    } 
} 

public class ViewBookActivity extends Activity { 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Intent intent = getIntent(); 
     ISBN = intent.getStringExtra("ISBN"); 
     setContentView(R.layout.activity_scan_result); 
     setBook(ISBN); 
    } 

    public void setBook(String ISBN) { 
     Book b = MainController.getBook(ISBN); 
     // Display book on screen 
    } 
} 

public class MainController { 
    static Realm realm = Realm.getDefaultInstance(); 

    public static Book getBook(String isbn) { 
     Book book = realm.where(Book.class) 
       .equalTo("isbn", isbn) 
       .findFirst(); 
     if (book == null) { 
      NetworkController.getBook(isbn); 
     } else { 
      return book; 
     } 
     return null; 
    } 
} 

public class NetworkController { 
    private static BookHandler bookHandler = new BookHandler(); 
    public static void getBook(String isbn) { 
     NetworkHelper.sendRequest(HTTPRequestMethod.GET, 
       "/books/" + isbn, bookHandler); 
    } 
} 


public class NetworkHelper { 
    private static String host = "http://crowdshelf-dev.herokuapp.com"; 
    public static void sendRequest(final HTTPRequestMethod requestMethod, final String route, final ResponseHandler responseHandler) { 
     new AsyncTask<Void, Void, Void>() { 
      @Override 
      protected void doInBackground(Void... params) { 
       try { 
        URL url = new URL(host + "/api" + route); 
        Log.d("NETDBTEST", "NetworkHelper request: " + requestMethod.toString() + " URL: " + url.toString()); 
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
        connection.connect(); 

        BufferedReader bReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 
        StringBuilder builder = new StringBuilder(); 
        String line = null; 
        while ((line = bReader.readLine()) != null) { 
         builder.append(line).append("\n"); 
        } 
        String jsonString = builder.toString(); 
        responseHandler.handleJsonResponse(jsonString); 
       return null; 
       } 
      } 
     }.execute(); 
    } 
} 

public class BookHandler implements ResponseHandler { 
    @Override 
    public void handleJsonResponse(String jsonString) { 
     Realm realm = Realm.getDefaultInstance(); 
     realm.beginTransaction(); 
     realm.createOrUpdateObjectFromJson(Book.class, jsonString); 
     realm.commitTransaction(); 
     realm.close(); 
    } 
} 

public class Book extends RealmObject{ 
    @PrimaryKey 
    private String isbn; 
    // Other fields, getters and setters 
} 

回答

0

1)首先,我不知道爲什麼你只是清洗數據庫中創建RealmActivity。活動是爲了顯示UI。如果它沒有任何目的,那麼將代碼移動到其他類。就像你可以創建一個新類RealmHandler並在那裏保存這種類型的代碼。

2)你並不需要創建一個靜態函數來獲取Realm對象。你可以有你的MainController功能是這樣的:

public class MainController { 


    public Book getBook(String isbn, Context context) { 
     Realm realm = Realm.getDefaultInstance(context); 

     Book book = realm.where(Book.class) 
       .equalTo("isbn", isbn) 
       .findFirst(); 
     if (book == null) { 
      NetworkController.getBook(isbn); 
     } else { 
      return book; 
     } 
     return null; 
    } 
} 

3)

怎麼能保證我打電話MainController.getBook()總是 返回一本書嗎?

你不能保證你總是得到一本書,例如在服務器上找不到書,或者沒有互聯網連接。你必須手動處理這種情況。

sendBook函數調用AsyncTaskAsyncTask在一個單獨的線程運行,所以當你打電話NetworkController.getBook(isbn)你無法回報你的服務器的測試結果。獲得結果的唯一方法是在BookHandler. handleJsonResponse

順便說一下,您無需實施Handler即可從AsyncTask獲得結果。您可以覆蓋函數來控制結果並在主線程上執行UI。

解決方案: 您可以用不同的方式,只要你喜歡解決這個問題,這裏的方式之一:

我)打電話MainController.getBook()得到一本書。如果未找到Book,則運行NetworkController.getBook(isbn); - 這將在不同的線程上運行,並且當前線程將向您的活動返回空值。如果爲null,那麼您只需忽略它或相應地執行操作。

ii)在AsyncTask中,您可以首先顯示一個ProgressBar,以便在從服務器獲取數據時告訴用戶正在處理某些內容。您可以在AsyncTaskonPreExecution函數中執行此操作。

iii)獲得結果功能AsyncTask。現在你回到你的主線了。如果你在同一個活動中,你可以直接更新你的用戶界面,但在你的情況下你不是。您不能直接返回數據,如在函數或更新UI中。

iv)您可以向您的MainActivity發送一個信號,表示網絡呼叫已完成,並且新數據位於數據庫中,以便更新視圖。你可以使用Event bus來達到這個目的。我個人使用Otto by Square:http://square.github.io/otto/

+0

iii)iv)我可以在'BookHandler'中用'ViewBookActivity'中的監聽器使用Event Bus或Otto來更新UI嗎?我想保留我的'BookHandler',因爲我有許多處理程序,它們的工作方式不同,我不希望所有代碼都在'onPostExecution'中混合在一起。 – tsorn

相關問題