我对Loopers和Realm感到麻烦。
我有Activity
在onCreate()中设置其Presenter
,然后调用其公共方法之一initFirstLaunch()
:
RealmChangeListener<CourseDetailed> listener = new RealmChangeListener<CourseDetailed>() {
@Override
public void onChange(CourseDetailed element) {
Log.i("renaud", "courseDetailed.addChangeListener onChange");
computeTableOfContent(element);
Log.i("renaud", "1");
playerViewContract.initWithCourseDetails(element);
Log.i("renaud", "2");
}
};
public void initFirstLaunch() {
courseDetailed = realm.where(CourseDetailed.class).contains("_id", courseId).findFirst();
if (courseDetailed == null) {
courseDetailed = realm.createObject(CourseDetailed.class, courseId);
}
courseDetailed.addChangeListener(listener);
Api.getInstance().backend.getCourse(courseId).enqueue(new CustomRetrofitCallBack<CourseDetailed>(playerViewContract) {
@Override
public void onResponseReceived(final CourseDetailed response) {
Realm.getDefaultInstance().executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response);
}
});
}
});
}
请注意playerViewContract
是我在这种情况下的活动。
我的问题是onChange()
有时会被调用,当它发生时它会阻止我的UI线程(并且最终会引发OutOfMemoryError
)。我的猜测是,我不是在一个looper线程中,但当我在Looper.prepare()
任何地方打电话时,它崩溃说我已经在一个。
发生了什么?
由于
编辑:添加initWithCourseDetailed代码
@Override
public void initWithCourseDetails(final CourseDetailed detailed) {
Log.i("renaud", "initWithCourseDetails");
mDrawer.post(new Runnable() {
@Override
public void run() {
String title = detailed.getName();
String subtitle = detailed.getCompany().getName();
if (detailed.getThumbnail() != null) {
String picUrl = AppConstants.SERVER_URL + "/api/" + detailed.getThumbnail();
final LinearLayout l = (LinearLayout) mNavigationView.findViewById(R.id.layout);
Picasso.with(ModulePlayerActivity.this)
.load(picUrl)
.config(Bitmap.Config.RGB_565)
.into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
l.setBackground(new BitmapDrawable(getResources(), bitmap));
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}
TextView nameTv = (TextView) mNavigationView.findViewById(R.id.drawer_header_name);
nameTv.setText(title);
TextView jobTv = (TextView) mNavigationView.findViewById(R.id.drawer_header_job);
jobTv.setText(subtitle);
supportInvalidateOptionsMenu();
}
});
}
Api.getInstance().backend.getCourse(courseId).enqueue(new CustomRetrofitCallBack<CourseDetailed>(playerViewContract) {
@Override
public void onResponseReceived(final CourseDetailed response) {
//TEST
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response);
}
});
} finally {
if (realm != null) {
realm.close();
}
realm = null;
}
}
});
答案 0 :(得分:1)
UI线程是一个Looper线程(它有looper Looper.getMainLooper()
),这意味着它具有自动更新。但是,自动更新意味着只要修改基础表,就会调用添加到ChangeListener
的{{1}},而不只是一次。
(我还应该注意,RealmObject
是由Realm&#39; RealmChangeListener
保留的弱引用,Context
也是to keep the autoupdate and the change listener intact even through GC, it has to be kept as a field reference。< / p>
虽然值得注意的是,如果ID未找到该元素,RealmObject
可以返回null,否则会立即返回该元素。)
所以在我看来,无论findFirst()
做什么,它都会一次又一次地发生并最终崩溃。
我希望我回答你的问题?