我試圖編寫一些代碼來獲得脫機的一些內容,可以稍後觀看。此內容是由jsons,圖像,視頻和PDF文件:領域實例和多線程
{
"elements": [
{
"id":"3b4c4f3da8bf9d1527010c5242e037b7",
"type":"media"
},
...
],
"id":"58088318ef0b4832f6c0e70b",
"content": "Hello World"
}
所以基本上我的問題是,我異步網絡調用和境界數據庫更新之間切換,並且我無法弄清楚如何構建它做好。
我抓住上面的JSON必須存儲它的領域,然後我打電話給每個元素的第二條路線得到DetailedElement
並存儲它。當元素包含可下載的文檔時,我必須下載它並將其路徑添加爲DetailedElement
的成員。事情是,我無法讓我的線程正確。
我idealy喜歡這個簽名的方法:
FooBar.prefetch(Context ctx, String id, Callback cb)
我的第一個步驟應該是確保它在非UI彎針線推出:我不知道該怎麼辦呢
public static void Bar(final Context ctx, final String id) {
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
final Realm realm = Realm.getDefaultInstance();
final Handler handler = new Handler();
MainThingToDownload mainThingToDownload = realm.where(MainThingToDownload.class).equalTo("id", id).findFirst();
if (mainThingToDownload != null) {
processMain(mainThingToDownload, realm, handler);
} else {
Api.getInstance().backendRepresentation.getMainThing(id).enqueue(new CustomRetrofitCallBack<>(null) {
@Override
public void onResponseReceived(final MainThingToDownload mainThingToDownload) {
handler.post(new Runnable() {
@Override
public void run() {
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(mainThingToDownload);
processMain(mainThingToDownload, realm, handler);
}
});
}
});
}
});
}
}
});
}
這是正確的做法嗎?保留其線程的領域引用和處理程序引用。然後我總是在我的網絡回調中這樣做:
handler.post(new Runnable() {
@Override
public void run() {
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
//... add downloaded object to realm or modifies one
}
});
}
});
我有很多不同的錯誤與我的代碼。大多數情況下,我不在應該使用Realm的線程上使用Realm,有時我使用已關閉的領域實例。
這是我應該怎麼做的? 謝謝,
我做什麼
一個Program
包含Module
列表,每個Module
包含Element
列表。
ProgramOfflineManager
public class ProgramOfflineManager extends AbstractOfflineManager {
private final static String TAG = "ModuleOfflineManager";
public ProgramOfflineManager(Context ctx, String id, ErrorDisplayerInterface errorDisplayerInterface) {
super(ctx, id, errorDisplayerInterface);
}
@Override
protected void makeOffline() throws IOException {
super.makeOffline();
ProgramOfflineManager.makeOffline(id, ctx);
}
@Override
protected void removeOffline() {
super.removeOffline();
ProgramOfflineManager.removeOffline(id, ctx);
}
public static void removeOffline(String programId, Context ctx) {
Log.i(TAG, "to be deleted");
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
//To be deleted
final Program program = realm.where(Program.class).equalTo("id", programId).findFirst();
Log.i("renaud", "courseDetailed matching is is not null : (detailed!=null)=>" + (program != null));
if (program != null) {
for (Module module : program.getModules()) {
CourseDetailed courseDetailed = realm.where(CourseDetailed.class).equalTo("id", module.getCourse()).equalTo("downloaded", true).findFirst();
if (courseDetailed != null) {
ModuleOfflineManager.removeOffline(module.getCourse(), ctx);
}
}
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
program.deleteFromRealm();
Log.i(TAG, "course has been deleted");
}
});
}
} finally {
if (realm != null) {
realm.close();
}
realm = null;
}
}
public static void makeOffline(final String programId, final Context ctx) throws IOException {
Api.Service360Interface backend = Api.getInstance().backend;
Response<Program> programResponse = backend.getProgram(programId).execute();
if (programResponse.isSuccessful()) {
final Program program = programResponse.body();
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
program.setDownloaded(true);
realm.copyToRealmOrUpdate(program);
}
});
for (final Module module : program.getModules()) {
long count = realm.where(CourseDetailed.class).equalTo("id", module.getCourse()).equalTo("downloaded", true).count();
if (count == 0) {
ModuleOfflineManager.makeOffline(module.getCourse(), ctx);
}
}
} finally {
if (realm != null) {
realm.close();
}
realm = null;
}
}
}
}
ModuleOfflineManager
public class ModuleOfflineManager extends AbstractOfflineManager {
private final static String TAG = "ModuleOfflineManager";
public ModuleOfflineManager(Context ctx, String id, ErrorDisplayerInterface errorDisplayerInterface) {
super(ctx, id, errorDisplayerInterface);
}
@Override
protected void makeOffline() throws IOException {
super.makeOffline();
ModuleOfflineManager.makeOffline(id, ctx);
}
@Override
protected void removeOffline() {
super.removeOffline();
ModuleOfflineManager.removeOffline(id, ctx);
}
public static void removeOffline(String courseId, Context ctx) {
Log.i(TAG, "to be deleted");
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
//To be deleted
final CourseDetailed detailed = realm.where(CourseDetailed.class).equalTo("id", courseId).findFirst();
Log.i("renaud", "courseDetailed matching is is not null : (detailed!=null)=>" + (detailed != null));
if (detailed != null) {
for (Element element : detailed.getElements()) {
Log.i(TAG, "next Element to suppress : " + element.getId());
final CourseElement courseElement = realm.where(CourseElement.class).equalTo("id", element.getId()).findFirst();
if (courseElement.getCollection() != null && courseElement.getCollection() == PostCollectionType.MEDIAS) {
Log.i(TAG, "it's a Media, erasing from db");
MediaDownloadUtils.eraseMedia(ctx, courseElement, realm);
}
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
courseElement.deleteFromRealm();
Log.i(TAG, "element has been deleted");
}
});
}
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
detailed.deleteFromRealm();
Log.i(TAG, "course has been deleted");
}
});
}
} finally {
if (realm != null) {
realm.close();
}
realm = null;
}
}
public static void makeOffline(final String courseId, final Context ctx) throws IOException {
Api.Service360Interface backend = Api.getInstance().backend;
Response<CourseDetailed> response = backend.getCourse(courseId).execute();
if (response.isSuccessful()) {
final CourseDetailed courseDetailedResponse = response.body();
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
courseDetailedResponse.saveEnums();
courseDetailedResponse.setDownloaded(true);
realm.copyToRealmOrUpdate(courseDetailedResponse);
}
});
for (final Element element : courseDetailedResponse.getElements()) {
Call<CourseElement> call = Api.getInstance().getCourseElement(element.getCollection(), element.getId(), courseId);
Response<CourseElement> courseElementResponse = call.execute();
if (courseElementResponse.isSuccessful()) {
final CourseElement courseElement = courseElementResponse.body();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
courseElement.setCourseElementType(CourseElementTypes.valueOf(element.getCollection()));
courseElement.saveEnums();
courseElement.setDownloaded(true);
realm.copyToRealmOrUpdate(courseElement);
MediaDownloadUtils.prefechMedia(ctx, courseElement);
}
});
}
}
} finally {
if (realm != null) {
realm.close();
}
realm = null;
}
}
}
}
AbstractOfflineManager
public abstract class AbstractOfflineManager implements OfflineManagerInterface {
private final static String TAG = "AbstractOfflineManager";
final protected Context ctx;
final protected String id;
final protected ErrorDisplayerInterface errorDisplayerInterface;
protected boolean status;
public AbstractOfflineManager(Context ctx, String id, ErrorDisplayerInterface errorDisplayerInterface) {
this.ctx = ctx;
this.id = id;
this.errorDisplayerInterface = errorDisplayerInterface;
}
protected void makeOffline() throws IOException {
//implementations in children
}
protected void removeOffline() {
//implementations in children
}
@Override
public CompoundButton.OnCheckedChangeListener getClickListener() {
return new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, final boolean isChecked) {
Log.i(TAG, "clic ! isChecked : " + isChecked);
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
status = isChecked;
if (isChecked) {
try {
makeOffline();
} catch (IOException e) {
e.printStackTrace();
errorDisplayerInterface.popError(null, e);
}
} else {
removeOffline();
}
}
}).start();
}
};
} }
現在我將創建一個ElementOfflineManager
每個線程都必須有它自己的Realm實例。你應該在完成之後立即關閉它,但不要以前。 –
例如你的onResponseReceived需要它自己的Realm實例,因爲它在一個單獨的線程上運行 –
這就是爲什麼我使用一個處理程序,我認爲「Realm.getDefaultInstance()」非常重要,我們應該嘗試保留對它的引用和它的線程。像這樣的一個操作會導致數十個異步網絡調用和更新數據庫。我只想在一切結束時關閉它。 –