【问题标题】:Activity - Service Inconsistent data with Realm活动 - 服务与领域不一致的数据
【发布时间】:2016-05-28 19:48:26
【问题描述】:

我对存储在 Realm 数据库中的数据有疑问。如果我更改 MainActivity 上的值,当我尝试从 NotificationListenerService 读取它时,数​​据不正确。

这是我的模型:

public class Model extends RealmObject {

    String name;
    boolean checked;


    public Model() {}

    public Model(String name, boolean checked) {
        this.name = name;
        this.checked = checked;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isChecked() {
        return checked;
    }

    public void setChecked(boolean checked) {
        this.checked = checked;
    }

}

我从 Application 类填充数据库:

public class ExampleApplication extends Application{

    @Override
    public void onCreate() {
        super.onCreate();
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(getApplicationContext()).deleteRealmIfMigrationNeeded().build();
        Realm.setDefaultConfiguration(realmConfiguration);
        Realm.getDefaultInstance().beginTransaction();
        Realm.getDefaultInstance().copyToRealm(new Model("Test1", true));
        Realm.getDefaultInstance().copyToRealm(new Model("Test2", true));
        Realm.getDefaultInstance().commitTransaction();
    }
}

我有一个活动:

  • 设备设置中带有通知侦听器服务链接的按钮
  • 显示模型状态的文本视图(选中或未选中)
  • 用于更改模型检查值的按钮

这是代码:

public class MainActivity extends AppCompatActivity {

    Button btnEnableService;
    Button btnChangeValue;
    TextView tvStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnEnableService = (Button) findViewById(R.id.btn_enable_service);
        btnChangeValue = (Button) findViewById(R.id.btn_change_value);
        tvStatus = (TextView) findViewById(R.id.tv_status);

        btnEnableService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
                }catch(ActivityNotFoundException anfe){
                    Toast.makeText(MainActivity.this, "Your device not supports Notification Listener Service", Toast.LENGTH_SHORT).show();
                }
            }
        });

        btnChangeValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean status = Realm.getDefaultInstance().where(Model.class).equalTo("name", "Test1").findFirst().isChecked();
                Realm.getDefaultInstance().beginTransaction();
                Realm.getDefaultInstance().where(Model.class).equalTo("name", "Test1").findFirst().setChecked(!status);
                Realm.getDefaultInstance().commitTransaction();
                updateView();
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        updateView();
    }

    private void updateView(){
        boolean status = Realm.getDefaultInstance().where(Model.class).equalTo("name", "Test1").findFirst().isChecked();
        tvStatus.setText("Status: " + status);
    }
}

当我单击 btnChangeValue 按钮时,我会更改 Realm 上的值,并且 textview 会使用新值进行更新。目前一切正常。

另一方面,我有一个服务来监听设备通知。很简单,只在LogCat上显示模型的状态值:

public class CustomNotificationListenerService extends NotificationListenerService{

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
        boolean status = Realm.getDefaultInstance().where(Model.class).equalTo("name", "Test1").findFirst().isChecked();
        Log.i("XXX", "Status: " + status);
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        super.onNotificationRemoved(sbn);
    }
}

我的问题是模型的checked值不一致,我从MainActivity和NotificationListenerService得到不同的值。

我做错了什么?

提前致谢!

【问题讨论】:

    标签: android android-service realm


    【解决方案1】:

    经过几个小时的测试,我解决了我的问题每次操作后关闭 Realm 实例

    所以,数据是一致的,我可以从 NotificationListenerService 和 MainActivity 查询。

    示例应用程序

    public class ExampleApplication extends Application{
    
        @Override
        public void onCreate() {
            super.onCreate();
            RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(getApplicationContext()).deleteRealmIfMigrationNeeded().build();
            Realm.setDefaultConfiguration(realmConfiguration);
            Realm mRealm = Realm.getDefaultInstance();
            mRealm.beginTransaction();
            mRealm.copyToRealm(new Model("Test1", true));
            mRealm.copyToRealm(new Model("Test2", true));
            mRealm.commitTransaction();
            mRealm.close();
        }
    }
    

    MainActivity

    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        btnChangeValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Realm mRealm = Realm.getDefaultInstance();
                boolean status = mRealm.where(Model.class).equalTo("name", "Test1").findFirst().isChecked();
                mRealm.beginTransaction();
                mRealm.where(Model.class).equalTo("name", "Test1").findFirst().setChecked(!status);
                mRealm.commitTransaction();
                mRealm.close();
                updateView();
            }
        });
    }
    ...
    

    CustomNotificationListenerService

    ...
    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
        Realm mRealm = Realm.getDefaultInstance();
        boolean status = mRealm.where(Model.class).equalTo("name", "Test1").findFirst().isChecked();
        mRealm.close();
        Log.i("XXX", "Status: " + status);
    }
    ...
    

    希望对你有帮助。

    【讨论】:

    • 这有一个巨大的内存泄漏,你不应该为你想调用的每个方法都调用 getInstance,调用一次,将它分配给一个变量,然后使用它
    • 每次调用 getInstance() 都必须有一个匹配的 close()
    • 是的,我的代码代表了一个非常简单的案例,我试图尽可能清楚地发布它。正如您所说,最佳做法是获取实例,将其保存在变量中,使用它,然后关闭它。在获取实例之前,我必须在每次调用时再次设置默认配置,因为如果没有,数据也不一致。我将编辑帖子。
    • 设置默认值应该只需要完成一次。如果它不起作用,则说明其他问题
    • 我知道,但是这里是所有代码,如果我不这样做,数据会不一致... :(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    相关资源
    最近更新 更多