将数据从 Service 发送到 Roomdatabase 的最佳方式

问题描述

我正在处理一个项目,我需要连接到服务器以获取数据并在地图上从该数据中绘制标记,每当数据发生变化时,我需要使用新位置更新地图。

>

我正在使用 Roomdatabase、Livedata 来观察更改和连接到服务器并将任何更新发送到存储库的服务。但最好的方法是什么?

提前致谢

编辑:

到目前为止,这是我的代码,我将尝试解释我设想它应该如何工作的方式

首先我有一个网关实体

@Entity(tableName = "gateway_table")
public class Gateway {
    
    private float temp;
    private float wertX;
    private float wertY;
    private String title;
    private boolean drawn;
    private ArrayList<String> ObjectANames = new ArrayList<>();


    @PrimaryKey(autoGenerate = true)
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public float getWertX() {
        return wertX;
    }

    public float getWertY() {
        return wertY;
    }

    public void setWertX(float wertX) {
        this.wertX = wertX;
    }

    public void setWertY(float wertY) {
        this.wertY = wertY;
    }

    public boolean isDrawn() {
        return drawn;
    }

    public void setDrawn(boolean drawn) {
        this.drawn = drawn;
    }

    public float getTemp() {
        return temp;
    }

    public void setTemp(float temp) {
        this.temp = temp;
    }

    public ArrayList<String> getobjectANames() {
        return ObjectANames;
    }

    public Gateway (float wertX,float wertY,String title,boolean drawn,ArrayList<String> ObjectANames){
        this.wertX = wertX;
        this.wertY = wertY;
        this.title = title;
        this.drawn = drawn;
        this.ObjectANames.addAll(ObjectANames);
    }
}

一个实体对象A

@Entity(tableName = "objectA_table")
public class ObjectA {
    private String gateway;
    private String name;
    private boolean drawn;


    @PrimaryKey(autoGenerate = true)
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public String getGateway() {
        return gateway;
    }

    public void setGateway(String gateway) {
        this.gateway = gateway;
    }

    public boolean isDrawn() {
        return drawn;
    }

    public void setDrawn(boolean drawn) {
        this.drawn = drawn;
    }

    public ObjectA(String gateway,String name,boolean drawn) {
        this.gateway = gateway;
        this.name = name;
        this.drawn = drawn;
    }


}

基本上每个网关在地图上都有一个位置(来自两个浮点数)、一个标题一个布尔值和一个包含来自 ObjectA 的名称的数组列表。 ObjectA 有一个名称一个包含它分配给的网关的字符串和一个布尔值。 所以一个网关可以有多个对象A,但每个对象A只有一个网关。

在两个 DAOS 中,我都有一个 findGateway/ObjectA 方法,在该方法中,我提供标题名称,然后返回具有该名称的网关或 objectA。

这是视图模型:

public class viewmodel extends Androidviewmodel {
    private Repository repository;
    private LiveData<List<ObjectA>> allObjectA;
    private LiveData<List<Gateway>> allGateways;
    private mutablelivedata<SocketService.mybinder> binderviewmodel = new mutablelivedata<>();

    public viewmodel(@NonNull Application application) {
        super(application);
        repository = new Repository(application);
        allObjectA = repository.getAllObjectA();
        allGateways = repository.getAllGateways();

    }

    public void insert(ObjectA objectA) throws InterruptedException {
        repository.insert(objectA);
    }

    public void delete(ObjectA objectA) throws InterruptedException {
        repository.delete(objectA);
    }

    public void deleteallObjectA() throws InterruptedException {
        repository.deleteallObjectA();
    }

    public void update(ObjectA objectA) throws InterruptedException {
        repository.update(objectA);
    }

    public ObjectA findobjectA(String ObjectAName) throws InterruptedException { return repository.findobjectA(ObjectAName);}

    public LiveData<List<ObjectA>> getAllObjectA(){
        return allObjectA;
    }


    public void insert(Gateway gateway) throws InterruptedException {
        repository.insert(gateway);
    }

    public void delete(Gateway gateway) throws InterruptedException {
        repository.delete(gateway);
    }

    public void deleteallGateways() throws InterruptedException {
        repository.deleteallGateways();
    }

    public void update(Gateway gateway) throws InterruptedException {
        repository.update(gateway);
    }

    public Gateway findGateway(String gatewayDesignation) throws InterruptedException { return repository.findGateway(gatewayDesignation);}

    public LiveData<List<Gateway>> getAllGateways(){
        return allGateways;
    }

    
    private ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name,IBinder iBinder) {
            SocketService.mybinder binder = (SocketService.mybinder) iBinder;
            binderviewmodel.postValue(binder);
        }

        @Override
        public void onServicedisconnected(ComponentName name) {
            binderviewmodel.postValue(null);
        }

    };

    public ServiceConnection getServiceConnection(){
        return serviceConnection;
    }

    public LiveData<SocketService.mybinder> getmybinder(){
        return binderviewmodel;
    }

}

这是我的服务:

public class SocketService extends Service {
    //public static final String IP_ADDRESS = "172.17.100.77";
   // public static final int SERVER_PORT = 5566;
    public static final int CONNECTION_STATUS=0;

    private Repository repository;

    private final IBinder mybinder = new mybinder();

    Thread thread;
    PrintWriter output;
    BufferedReader input;
    Socket socket;

    MediaPlayer player;

    ArrayList<ObjectA> objectAArrayList;


    @Override
    public IBinder onBind(Intent intent) {

        System.out.println("I am in Ibinder onBind method");
        return mybinder;
    }

    public class mybinder extends Binder {
        public SocketService getService() {
            System.out.println("I am in Localbinder ");
            return SocketService.this;

        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        repository = new Repository(getApplication());

        player = MediaPlayer.create(getApplicationContext(),Settings.System.DEFAULT_ringtone_URI);
        player.setLooping(true);
        player.start();
    }

    private void sendMessageConnected() {
        EventBus.getDefault().post(new IntentServiceResult(CONNECTION_STATUS,"Song is playing"));
    }

    private void sendMessageObjectGone(ObjectA objectA,ObjectA objectAOld) {
        EventBus.getDefault().post(new IntentServiceResult(1,objectA,objectAOld));
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {
        super.onStartCommand(intent,flags,startId);
        objectAArrayList = new ArrayList<>();
        objectAArrayList.add(new ObjectA("gate3","ObjectA1",false));
        objectAArrayList.add(new ObjectA("gate2","ObjectA2","ObjectA3",false));
        objectAArrayList.add(new ObjectA("gate4",false));
        objectAArrayList.add(new ObjectA("gate3",false));



        thread = new Thread(new connectSocket());
        thread.start();
        return START_STICKY;
    }


    class connectSocket implements Runnable {

        @Override
        public void run() {

            while (player.isPlaying()) {
                sendMessageConnected();

            for (int i = 0; i< objectAArrayList.size(); i++){
                    try {
                        if(repository.findobjectA(objectAArrayList.get(i).getName()) == null){
                            repository.insert(objectAArrayList.get(i));
                            repository.update(objectAArrayList.get(i));

                            Gateway gateway = repository.findGateway(objectAArrayList.get(i).getGateway());
                            gateway.getobjectANames().add(objectAArrayList.get(i).getName());
                            if(repository.findGateway(gateway.getTitle()).isDrawn()){
                                gateway.setDrawn(true);
                                repository.update(gateway);
                            }else{
                                gateway.setDrawn(false);
                                repository.update(gateway);
                            }

                            Thread.sleep(2000);
                        }else {
                            ObjectA objectA = repository.findobjectA(objectAArrayList.get(i).getName());
                            ObjectA ObjectAold = repository.findobjectA(objectAArrayList.get(i).getName());
                            Gateway oldGateway = repository.findGateway(objectA.getGateway());



                            objectA.setGateway(objectAArrayList.get(i).getGateway());
                            repository.update(objectA);
                            Gateway newGateway = repository.findGateway(objectAArrayList.get(i).getGateway());

                            if(repository.findGateway(oldGateway.getTitle()).isDrawn() && repository.findGateway(objectAArrayList.get(i).getGateway()).isDrawn())
                            {
                                sendMessageObjectGone(objectA,ObjectAold);
                            }else
                            {
                                oldGateway.getobjectANames().remove(ObjectAold.getName());
                                newGateway.getobjectANames().add(objectA.getName());
                                repository.update(oldGateway);
                                repository.update(newGateway);
                            }

                            ObjectA objectA1 = repository.findobjectA(objectAArrayList.get(i).getName());
                            objectA1.setDrawn(false);
                            repository.update(objectA1);

                            Thread.sleep(2000);
                        }
                    } catch (InterruptedException e) {
                        e.printstacktrace();
                    }
                }
            }

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        /*try {
            socket.close();
        } catch (IOException e) {
            e.printstacktrace();
        }*/
        player.stop();
    }
}

我还没有访问服务器的权限,所以我只是在运行一个模拟。我正在启动一个播放器,只要它在服务上就应该继续工作。 我在开始时初始化了对某些 ObjectA 的一些更新,并在每次更新存储库时检查它们。

最后但并非最不重要的地图活动,但首先我想解释它应该如何工作。每个网关可以有多个 ObjectA,但在地图上,每个网关旁边只应绘制其中的三个。所以在绘制标记之前,我总是检查三个位置中的一个是否空闲。

这是 GatewayMarker 类,它有一个布尔数组,用于查看哪些位置是空闲的

public class GatewayMarker extends MapMarker {

    private Gateway gateway;
    private boolean[] posTaken;

    public GatewayMarker(Context context,Gateway gateway,boolean[] posTaken) {
        super(context,gateway.getWertX(),gateway.getWertY(),gateway.getTitle());

        this.gateway = gateway;
        this.posTaken = posTaken;
        setimageResource(R.drawable.gateway_foreground);
    }

    public float getXfirstPos() {
        return gateway.getWertX() + 0.05f;
    }

    public float getYfirstPos() {
        return gateway.getWertY() + 0.05f;
    }

    public float getXSecondPos() {
        return gateway.getWertX() - 0.05f;
    }

    public float getYSecondPos() {
        return gateway.getWertY() + 0.05f;
    }

    public float getXThirdPos() {
        return gateway.getWertX();
    }

    public float getYThirdPos() {
        return gateway.getWertY() - 0.05f;
    }

    public boolean[] getPosTaken() {
        return posTaken;
    }



}

这是 ObjectAMarker

public class ObjectAMarker extends MapMarker {

    private int pos;

    public ObjectAMarker(Context context,float x,float y,int pos) {
        super(context,x,y,name);
        this.pos = pos;
        setimageResource(R.drawable.kuh2_foreground);
    }

    public int getPos() {
        return pos;
    }

}

和地图活动

public class MapMarkerActivity extends AppCompatActivity {
    public static final int REQUEST_CONNECTION_STATUS = 0;

    private MapViewExt mapView;
    private TextView textView;
    private EditText textx;
    private EditText textY;
    private Button button;
    private Button buttonDelete;
    private Boolean calledFirstTime = true;
    private Boolean gatewayMoved = false;
    private FrameLayout frameLayout;
    private Observer<List<Gateway>> observerGateways;
    private Observer<List<ObjectA>> observerObjectA;

    private ArrayList<GatewayMarker> gatewayMarkers;
    private ArrayList<ObjectAMarker> ObjectAMarkers;

    private viewmodel viewmodel;

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

        textx = findViewById(R.id.edit_text_x);
        textY = findViewById(R.id.edit_text_y);
        button = findViewById(R.id.button);
        buttonDelete = findViewById(R.id.button_delete);
        frameLayout = findViewById(R.id.frame_layout_show_barn);
        textView = findViewById(R.id.text_view_connection_mapmarker);

        viewmodel = new viewmodelProvider(this,viewmodelProvider.AndroidviewmodelFactory.getInstance(this.getApplication())).get(viewmodel.class);


        buttonDelete.setEnabled(false);
        button.setEnabled(false);

        mapView = makeMapView();

        if (mapView != null) {
            mapView.setId(R.id.mapview_id);
            mapView.setSaveEnabled(true);
            frameLayout.addView(mapView);
        }


    }

    private MapViewExt makeMapView() {
        // hier Code to create the map
    }


    private GatewayMarker findGatewayMarker(String title) {
        GatewayMarker gatewayMarker1 = null;
        for (GatewayMarker gatewayMarker : gatewayMarkers) {
            if (gatewayMarker.getName().equals(title)) {
                gatewayMarker1 = gatewayMarker;
            }
        }
        return gatewayMarker1;
    }

    private ObjectAMarker findobjectAMarker(String name) {
        ObjectAMarker objectAMarker = null;
        for (ObjectAMarker objectAMarker1 : ObjectAMarkers) {
            if (objectAMarker1.getName().equals(name)) {
                objectAMarker = objectAMarker1;
            }
        }
        return objectAMarker;
    }


    private ObjectAMarker addNewObjectAMarker(MapViewExt mapView,int pos) {
        ObjectAMarker objectAMarker = new ObjectAMarker(this,name,pos);
        mapView.addMarker(objectAMarker);
        return objectAMarker;
        //MarkerApiKt.addMarker(mapView,marker,-0.5f,0f,0f);
    }

    private GatewayMarker addNewGatewayMarker(MapViewExt mapView,Gateway gateway) {
        boolean[] posTaken = new boolean[3];
        posTaken[0] = false;
        posTaken[1] = false;
        posTaken[2] = false;
        GatewayMarker gatewayMarker = new GatewayMarker(this,gateway,posTaken);
        mapView.addMarker(gatewayMarker);
        return gatewayMarker;
    }

    @Override
    protected void onResume() {
        super.onResume();
        EventBus.getDefault().register(this);

        gatewayMarkers = new ArrayList<>();
        ObjectAMarkers = new ArrayList<>();

        observerGateways = new Observer<List<Gateway>>() {
            @Override
            public void onChanged(List<Gateway> gateways) {
                for (Gateway gateway : gateways) {

                    if (!gateway.isDrawn()) {


                        if (calledFirstTime || gatewayMoved) {

                            gatewayMoved = false;
                            GatewayMarker gatewayMarker = addNewGatewayMarker(mapView,gateway);
                            gatewayMarkers.add(gatewayMarker);

                            gateway.setDrawn(true);
                            try {
                                viewmodel.update(gateway);
                            } catch (InterruptedException e) {
                                e.printstacktrace();
                            }

                            for (int i = 0; i < gateway.getobjectANames().size(); i++) {
                                ObjectAMarker objectAMarker;
                                if (!gatewayMarker.getPosTaken()[0]) {
                                    objectAMarker = addNewObjectAMarker(mapView,gatewayMarker.getXfirstPos(),gatewayMarker.getYfirstPos(),gateway.getobjectANames().get(i),0);
                                    ObjectAMarkers.add(objectAMarker);

                                    try {
                                        ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                        objectA.setDrawn(true);
                                        viewmodel.update(objectA);
                                    } catch (InterruptedException e) {
                                        e.printstacktrace();
                                    }

                                    gatewayMarker.getPosTaken()[0] = true;

                                } else if (!gatewayMarker.getPosTaken()[1]) {
                                    objectAMarker = addNewObjectAMarker(mapView,gatewayMarker.getXSecondPos(),gatewayMarker.getYSecondPos(),1);
                                    ObjectAMarkers.add(objectAMarker);

                                    try {
                                        ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                        objectA.setDrawn(true);
                                        viewmodel.update(objectA);
                                    } catch (InterruptedException e) {
                                        e.printstacktrace();
                                    }

                                    gatewayMarker.getPosTaken()[1] = true;

                                } else if (!gatewayMarker.getPosTaken()[2]) {
                                    objectAMarker = addNewObjectAMarker(mapView,gatewayMarker.getXThirdPos(),gatewayMarker.getYThirdPos(),2);
                                    ObjectAMarkers.add(objectAMarker);

                                    try {
                                        ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                        objectA.setDrawn(true);
                                        viewmodel.update(objectA);
                                    } catch (InterruptedException e) {
                                        e.printstacktrace();
                                    }

                                    gatewayMarker.getPosTaken()[2] = true;
                                    return;
                                }

                            }
                        }

                    } else {
                        GatewayMarker gatewayMarker = findGatewayMarker(gateway.getTitle());
                        for (int i = 0; i < gateway.getobjectANames().size(); i++) {
                            try {
                                if (!viewmodel.findobjectA(gateway.getobjectANames().get(i)).isDrawn()) {

                                    if (!gatewayMarker.getPosTaken()[0]) {
                                        ObjectAMarker objectAMarker = findobjectAMarker(gateway.getobjectANames().get(i));
                                        ObjectAMarkers.remove(objectAMarker);

                                        ObjectAMarkers.add(addNewObjectAMarker(mapView,0));

                                        try {
                                            ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                            objectA.setDrawn(true);
                                            viewmodel.update(objectA);
                                        } catch (InterruptedException e) {
                                            e.printstacktrace();
                                        }

                                        gatewayMarker.getPosTaken()[0] = true;
                                    } else if (!gatewayMarker.getPosTaken()[1]) {
                                        ObjectAMarker objectAMarker = findobjectAMarker(gateway.getobjectANames().get(i));
                                        ObjectAMarkers.remove(objectAMarker);
                                        ObjectAMarkers.add(addNewObjectAMarker(mapView,1));

                                        try {
                                            ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                            objectA.setDrawn(true);
                                            viewmodel.update(objectA);
                                        } catch (InterruptedException e) {
                                            e.printstacktrace();
                                        }

                                        gatewayMarker.getPosTaken()[1] = true;
                                    } else if (!gatewayMarker.getPosTaken()[2]) {
                                        ObjectAMarker objectAMarker = findobjectAMarker(gateway.getobjectANames().get(i));
                                        ObjectAMarkers.remove(objectAMarker);
                                        ObjectAMarkers.add(addNewObjectAMarker(mapView,2));

                                        try {
                                            ObjectA objectA = viewmodel.findobjectA(gateway.getobjectANames().get(i));
                                            objectA.setDrawn(true);
                                            viewmodel.update(objectA);
                                        } catch (InterruptedException e) {
                                            e.printstacktrace();
                                        }

                                        gatewayMarker.getPosTaken()[2] = true;
                                    } else {
                                        return;
                                    }
                                }
                            } catch (InterruptedException e) {
                                e.printstacktrace();
                            }
                        }

                    }
                }
                calledFirstTime = false;
            }

        };
        observerObjectA = new Observer<List<ObjectA>>() {

            @Override
            public void onChanged(List<ObjectA> objectAS) {

            }
        };


        viewmodel.getAllObjectA().observe(this,observerObjectA);
        viewmodel.getAllGateways().observe(this,observerGateways);
    }

    @Override
    protected void onPause() {
        super.onPause();

        List<ObjectA> allKühe = viewmodel.getAllObjectA().getValue();
        List<Gateway> allGateways = viewmodel.getAllGateways().getValue();

        for (ObjectA objectA : allKühe) {
            objectA.setDrawn(false);
            try {
                viewmodel.update(objectA);
            } catch (InterruptedException e) {
                e.printstacktrace();
            }
        }


        for (Gateway gateway : allGateways) {
            gateway.setDrawn(false);
            try {
                viewmodel.update(gateway);
            } catch (InterruptedException e) {
                e.printstacktrace();
            }
        }
        viewmodel.getAllGateways().removeObserver(observerGateways);
        viewmodel.getAllObjectA().removeObserver(observerObjectA);
        calledFirstTime = true;

        for (int i = 0; i < ObjectAMarkers.size(); i++) {
            MarkerApiKt.removeMarker(mapView,ObjectAMarkers.get(i));
        }

        ObjectAMarkers.clear();
        for (int i = 0; i < gatewayMarkers.size(); i++) {
            MarkerApiKt.removeMarker(mapView,gatewayMarkers.get(i));
        }
        gatewayMarkers.clear();

        EventBus.getDefault().unregister(this);

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getconnectionstatus(IntentServiceResult intentServiceResult) throws InterruptedException {
        if (intentServiceResult.getResult() == REQUEST_CONNECTION_STATUS) {
            textView.setText(intentServiceResult.getResultvalue());
        }

        if (intentServiceResult.getResult() == 1) {
            ObjectA objectA = intentServiceResult.getResultObjectA();
            ObjectA objectAOld = intentServiceResult.getResultObjectAOld();
            Gateway gateway = viewmodel.findGateway(objectA.getGateway());
            Gateway gatewayOld = viewmodel.findGateway(objectAOld.getGateway());

            gatewayOld.getobjectANames().remove(objectAOld.getName());
            gateway.getobjectANames().add(objectA.getName());

            viewmodel.update(gatewayOld);
            viewmodel.update(gateway);

            ObjectAMarker objectAMarker = findobjectAMarker(objectAOld.getName());
            GatewayMarker gatewayMarker = findGatewayMarker(gatewayOld.getTitle());
            gatewayMarker.getPosTaken()[objectAMarker.getPos()] = false;
            MarkerApiKt.removeMarker(mapView,objectAMarker);
        }
    }


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

    }
}

基本上问题是什么,当我打开地图Activity时它正常工作,但是假设我在mapActivity之上打开另一个Activity并且数据库中发生了变化,当我回到mapActivity时我发现了两个实例相同的标记。我通过数据库检查器注意到,我最终在 Gateaway 对象的 ArrayList 中得到了两个相同的字符串,这是不应该发生的。

一个问题是,现在该服务设置为进行更改并休眠 2 秒,这可能不会保持这种状态,但是当我不让它休眠时,即使我在 Map Activity 中我确实有不一致之处。

编辑 2: 数据库

@androidx.room.Database(entities = {ObjectA.class,Gateway.class},version = 26)
@TypeConverters({Converters.class})
public abstract class Database extends RoomDatabase {

    private static volatile Database instance;

    public abstract ObjectADAO cowDAO();
    public abstract GatewayDAO gatewayDAO();

    public static synchronized Database getInstance(Context context){

        if (instance == null){
            instance = Room.databaseBuilder(context.getApplicationContext(),Database.class,"database")
                    .fallbackToDestructiveMigration()
                    .build();
        }
        return instance;
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)