是否有可能在Realm(Java,Android)中進行進程間通信。因此,如果我們更新一個Process的RealmObject字段的值,我們是否會在另一個進程中觸發RealmChangeListener(對應於提及的RealmObject)。我認爲Realm的版本至少是2.0.2。在Android的Realm中可以進行內部進程通信嗎?
回答
境界2.0.0及以後支持進程間通知非加密的國度,但are some edge cases that aren't covered yet (multi-process migrations, primarily).
我已經把一個樣本項目,它爲我工作。
在這裏,RecyclerView顯示從屬於遠程進程的廣播接收器插入的狗。
10-11 20:53:46.340 7302-7302/com.zhuinden.realm_multiprocess_example I/MainActivity: Activity in Process [7302]
10-11 20:53:46.344 7302-7302/com.zhuinden.realm_multiprocess_example D/RealmManager: Incrementing Activity Count [0]: opening Realm.
10-11 20:53:46.352 7302-7302/com.zhuinden.realm_multiprocess_example D/RealmManager: Increment: Count [1]
10-11 20:54:01.352 7560-7560/com.zhuinden.realm_multiprocess_example:remote D/AlarmReceiver: Alarm received in process [7560]
10-11 20:54:01.352 7560-8705/com.zhuinden.realm_multiprocess_example:remote I/AlarmReceiver: Inserting DOGE [Juice]
完整源代碼:
public class RealmManager {
private static final String TAG = "RealmManager";
static Realm realm;
static RealmConfiguration realmConfiguration;
public static RealmConfiguration buildDefaultRealmConfiguration() {
return new RealmConfiguration.Builder()
.deleteRealmIfMigrationNeeded()
.build();
}
public static void initializeRealmConfig(Context appContext) {
if(realmConfiguration == null) {
Realm.init(appContext);
Log.d(TAG, "Initializing Realm configuration.");
setRealmConfiguration(buildDefaultRealmConfiguration());
}
}
public static void setRealmConfiguration(RealmConfiguration realmConfiguration) {
RealmManager.realmConfiguration = realmConfiguration;
Realm.setDefaultConfiguration(realmConfiguration);
}
private static int activityCount = 0;
public static Realm getRealm() {
return realm;
}
public static void incrementCount() {
if(activityCount == 0) {
if(realm != null) {
if(!realm.isClosed()) {
Log.w(TAG, "Unexpected open Realm found.");
realm.close();
}
}
Log.d(TAG, "Incrementing Activity Count [0]: opening Realm.");
realm = Realm.getDefaultInstance();
}
activityCount++;
Log.d(TAG, "Increment: Count [" + activityCount + "]");
}
public static void decrementCount() {
activityCount--;
Log.d(TAG, "Decrement: Count [" + activityCount + "]");
if(activityCount <= 0) {
Log.d(TAG, "Decrementing Activity Count: closing Realm.");
activityCount = 0;
realm.close();
if(Realm.compactRealm(realmConfiguration)) {
Log.d(TAG, "Realm compacted successfully.");
}
realm = null;
}
}
}
public class MainActivity
extends AppCompatActivity {
private static final String TAG = "MainActivity";
@BindView(R.id.recyclerview)
RecyclerView recyclerView;
Realm realm;
@Override
protected void onCreate(Bundle savedInstanceState) {
RealmManager.initializeRealmConfig(getApplicationContext());
Log.i(TAG, "Activity in Process [" + android.os.Process.myPid() + "]");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
RealmManager.incrementCount(); //lazy for retained fragment
realm = RealmManager.getRealm();
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new RealmRecyclerViewAdapter<Dog, DogViewHolder>(this, realm.where(Dog.class).findAllAsync(), true) {
@Override
public DogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView textView = new TextView(MainActivity.this);
RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(layoutParams);
return new DogViewHolder(textView);
}
@Override
public void onBindViewHolder(DogViewHolder holder, int position) {
holder.bind(getData().get(position));
}
});
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 15);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
addNotification(alarmManager, pendingIntent, calendar.getTimeInMillis());
}
public void addNotification(AlarmManager alarmManager, PendingIntent pendingIntent, long timeOfNotification) {
if(Build.VERSION.SDK_INT < 19) {
alarmManager.set(AlarmManager.RTC_WAKEUP, timeOfNotification, pendingIntent);
} else if(Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 23) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeOfNotification, pendingIntent);
} else if(Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeOfNotification, pendingIntent);
}
}
@Override
protected void onDestroy() {
RealmManager.decrementCount();
super.onDestroy();
}
}
public class DogViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public DogViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
public void bind(Dog dog) {
textView.setText(dog.getName());
}
}
public enum DogNames {
Jack,
Jill,
Joe,
Jarble,
Juice,
Jen,
Jim,
Munch,
Slurp,
Boop,
Largo,
Boson,
Pete,
Boner,
Derp,
Roger,
Bunbun,
Twix,
Dog
}
public class Dog extends RealmObject {
@PrimaryKey
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AlarmReceiver extends BroadcastReceiver {
private static final String TAG = "AlarmReceiver";
RealmConfiguration realmConfiguration;
Executor executor;
@Override
@SuppressLint("NewApi")
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Alarm received in process [" + android.os.Process.myPid() + "]");
Realm.init(context);
if(realmConfiguration == null) {
realmConfiguration = RealmManager.buildDefaultRealmConfiguration();
}
if(executor == null) {
executor = Executors.newSingleThreadExecutor();
}
executor.execute(() -> {
try(Realm r = Realm.getInstance(realmConfiguration)) {
if(Looper.getMainLooper() == Looper.myLooper()) {
Log.i(TAG, "UI thread transaction: this should be fixed!");
}
r.executeTransaction(realm -> {
Dog dog = new Dog();
long id = realm.where(Dog.class).findAll().size()+1;
dog.setId(id);
dog.setName(DogNames.values()[((Long)id).intValue() % DogNames.values().length].name());
realm.insert(dog);
Log.i(TAG, "Inserting DOGE [" + dog.getName() + "]");
});
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.zhuinden.realm_multiprocess_example"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".AlarmReceiver"
android:process=":remote"/>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhuinden.realm_multiprocess_example.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenCentral()
jcenter()
maven {url "https://clojars.org/repo/"}
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath "io.realm:realm-gradle-plugin:2.0.2"
classpath 'me.tatarka:gradle-retrolambda:3.2.5'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenCentral()
jcenter()
maven {url "https://clojars.org/repo/"}
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'realm-android'
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.zhuinden.realm_multiprocess_example"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
// Exclude file to avoid
// Error: Duplicate files during packaging of APK
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
compile "com.android.support:recyclerview-v7:24.2.1"
apt 'com.jakewharton:butterknife-compiler:8.4.0'
compile 'com.jakewharton:butterknife:8.4.0'
apt 'dk.ilios:realmfieldnameshelper:1.1.0'
compile 'io.realm:android-adapters:1.3.0'
}
我已看過此頁面。但我沒有遵守預期的行爲。你有沒有工作的例子? – nature1729
那麼,預期的行爲是什麼,它是如何發生的? SharedRealm中的'waitForChange'應該處理這個問題。 – EpicPandaForce
代替觸發器,waitForChange在本質上將被阻塞。 – nature1729
- 1. 線程之間可以通過LINX通信進行通信嗎?
- 2. 我可以在Android中使用全局緩衝區嗎?其他進程可以進行通信,甚至可以從本地C++代碼進行通信
- 3. Android可以通過NFC與Window Phone進行通信嗎?
- 4. 如何在C#中進行進程間通信時進行進程間通信?
- 5. 兩個Android手機之間可以進行通信嗎?
- 6. 是否可以通過subprocess.Popen與子子進程進行通信?
- 7. Java程序可以和終端進行通信嗎?
- 8. 內部進程通信示例(IPC)
- 9. Android和iPhone可以通過藍牙SPP配置文件進行通信嗎?
- 10. 可以通過android服務提供兩個接口進行通信嗎?
- 11. 如何在android中進行Socket通信?
- 12. NSNotificationCenter可以在不同的應用程序之間進行通信嗎?
- 13. 可以使用anymote協議在兩個android設備之間進行通信嗎?
- 14. 我可以在內部進行交易關閉嗎
- 15. 如何在Firefox插件和android進程之間進行通信?
- 16. 進程間通信是套接字通信可靠協議嗎?
- 17. 兩個應用程序可以通過UDP數據包進行通信嗎?
- 18. AJAX可以通過非SSL進行嗎?
- 19. 我可以使用window.postMessage進行同步跨域通信嗎?
- 20. angular.js可以與JSTL表達式語言進行通信嗎?
- 21. HTML5可以與Java Serversocketchannel進行通信嗎?
- 22. 可以使用單個端口進行快速IPC通信嗎?
- 23. 我可以使用silverlight 4.0進行視頻通信嗎?
- 24. 我們可以使用JSch進行SSH密鑰通信嗎?
- 25. 可以通過進程sighandler處理linux信號SIG_KILL嗎?
- 26. Android NFC:我可以進行雙向信息交換嗎?
- 27. 兩個Windows應用程序可以使用命令行進行通信嗎?
- 28. 兩個QProcesses可以通過信號和插槽進行通信嗎?
- 29. chrome擴展名:擴展名可以與外部iframe進行通信嗎?
- 30. 執行進程通信
你能否詳細說明 – nature1729
@bigdestroyer你知道Realm不是關係型的,不會暴露遊標,對嗎?所以它不支持ContentProvider呢? – EpicPandaForce