管灌系统巡查员智能手机App
app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java
@@ -26,15 +26,21 @@
import com.dayu.pipirrapp.R;
import com.dayu.pipirrapp.activity.AddIssueActivity;
import com.dayu.pipirrapp.bean.db.CenterPointBean;
import com.dayu.pipirrapp.bean.db.DivideBean;
import com.dayu.pipirrapp.bean.db.InspectionBean;
import com.dayu.pipirrapp.bean.db.InspectionLocationBean;
import com.dayu.pipirrapp.bean.db.LatLonBean;
import com.dayu.pipirrapp.bean.db.MarkerBean;
import com.dayu.pipirrapp.bean.db.PipeNetworkBean;
import com.dayu.pipirrapp.bean.net.CenterPointResult;
import com.dayu.pipirrapp.bean.net.DivideListResult;
import com.dayu.pipirrapp.bean.net.DivideResult;
import com.dayu.pipirrapp.bean.net.InsectionResult;
import com.dayu.pipirrapp.bean.net.InspectionRequest;
import com.dayu.pipirrapp.bean.net.MarkerListResult;
import com.dayu.pipirrapp.bean.net.MarkerResult;
import com.dayu.pipirrapp.bean.net.PipeNetworkListResult;
import com.dayu.pipirrapp.bean.net.PipeNetworkResult;
import com.dayu.pipirrapp.dao.DaoSingleton;
import com.dayu.pipirrapp.databinding.FragmentMapBinding;
import com.dayu.pipirrapp.net.ApiManager;
@@ -72,6 +78,7 @@
import java.util.stream.Collectors;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
/**
@@ -99,11 +106,19 @@
    List<InspectionLocationBean> aginShowlocationBeans;
    //web加载时网页还没加载完时的数据
    List<MarkerBean> webNoFinishMarkerData = new ArrayList<>();
    List<DivideBean> webNoFinishDivideData = new ArrayList<>();
    //所有的Marker数据键为marker的Id
    Map<String, MarkerBean> markerBeanSet = new HashMap<>();
    //所有分水房
    Map<String, DivideBean> divideBeanMap = new HashMap<>();
    //中心点坐标
    public double centerLng;
    public double centerLat;
    MarkerBean mMarkerBean;
    // 添加CompositeDisposable来管理所有订阅
    private CompositeDisposable compositeDisposable = new CompositeDisposable();
    @Override
    public void onAttach(@NonNull Context context) {
@@ -116,8 +131,16 @@
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        Log.i(TAG, "onCreate");
        mInspectionState = SharedPreferencesHelper.getInstance(this.getContext()).get(CommonKeyName.inspectionState, 0);
        // 添加刷新数据的监听
        LiveEventBus.get(CommonKeyName.refreshData).observe(this, o -> {
            getCenterPoint();
            getMarkerData();
            getDivideList();
        });
    }
    @Override
@@ -130,7 +153,6 @@
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentMapBinding.inflate(inflater, container, false);
        mapFragmenObserver.setmWebView(binding.webView);
        Log.i("MapFragment", "onCreateView");
@@ -139,13 +161,87 @@
        MyWebViewInterface myWebViewInterface = new MyWebViewInterface(MapFragment.this);
        mWebView.addJavascriptInterface(myWebViewInterface, "Android");
        mWebView.loadUrl("file:///android_asset/index.html");
        getCenterPoint();
        // 异步加载本地数据
        loadLocalData();
        initView();
        initWeb();
        getMarkerData();
        chageInspecState(mInspectionState);
        return binding.getRoot();
    }
    /**
     * 异步加载本地数据
     */
    private void loadLocalData() {
        // 异步加载中心点数据
        compositeDisposable.add(
            DaoSingleton.getAsynchInstance(this.getContext()).centerPointDao().findFirst()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(result -> {
                    centerPointBean = result;
                    if (centerPointBean == null) {
                        getCenterPoint();
                    } else {
                        jumpCenterPoint();
                    }
                }, throwable -> {
                    Log.e(TAG, "Load centerPoint error: " + throwable);
                    getCenterPoint();
                }, () -> {
                    // 当Maybe为空时调用
                    getCenterPoint();
                })
        );
        // 异步加载取水口数据
        compositeDisposable.add(
            DaoSingleton.getAsynchInstance(this.getContext()).markerDao().getAll()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(markers -> {
                    if (markers == null || markers.isEmpty()) {
                        getMarkerData();
                    } else {
                        for (MarkerBean marker : markers) {
                            markerBeanSet.put(marker.getId(), marker);
                            setMapMarker(marker);
                        }
                    }
                }, throwable -> {
                    Log.e(TAG, "Load markers error: " + throwable.getMessage());
                    getMarkerData();
                }, () -> {
                    // 当Maybe为空时调用
                    getMarkerData();
                })
        );
        // 异步加载分水房数据
        compositeDisposable.add(
            DaoSingleton.getAsynchInstance(this.getContext()).divideDao().getAll()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(divides -> {
                    if (divides == null || divides.isEmpty()) {
                        getDivideList();
                    } else {
                        for (DivideBean divide : divides) {
                            divideBeanMap.put(divide.getId(), divide);
                            setMapDivide(divide);
                        }
                    }
                }, throwable -> {
                    Log.e(TAG, "Load divides error: " + throwable.getMessage());
                    getDivideList();
                }, () -> {
                    // 当Maybe为空时调用
                    getDivideList();
                })
        );
    }
    private void initWeb() {
@@ -207,7 +303,7 @@
                super.onPageFinished(view, url);
                //页面加载完成
                webViewIsFinished = true;
                initLocalData();
                webFinishInitLocalData();
                aginShowLocation(null);
            }
@@ -215,16 +311,22 @@
    }
    /**
     * 初始化本地数据
     * web加载完初始化本地数据
     */
    public void initLocalData() {
        //跳转中心点
        centerPointBean = DaoSingleton.getInstance(MapFragment.this.getContext()).centerPointDao().findFirst();
        jumpCenterPoint();
    public void webFinishInitLocalData() {
        // 只在本地没有数据时获取中心点
        if (centerPointBean != null) {
            jumpCenterPoint();
        }
        //添加因webview没有加载完成导致没有添加的地图标注
        if (!webNoFinishMarkerData.isEmpty()) {
            for (MarkerBean bean : webNoFinishMarkerData) {
                setMapMarker(bean);
            }
        }
        if (!webNoFinishDivideData.isEmpty()) {
            for (DivideBean bean : webNoFinishDivideData) {
                setMapDivide(bean);
            }
        }
        //显示所有取水口
@@ -237,7 +339,6 @@
        }
    }
    /**
     * 获取取水口列表
     */
@@ -246,9 +347,7 @@
            @Override
            public void onNext(BaseResponse<MarkerListResult> t) {
                if (t.isSuccess()) {
                    if (t.getContent().getObj() != null && !t.getContent().getObj().isEmpty()) {
                        List<MarkerBean> markerBeans = t.getContent().getObj().stream()
                                .map(result -> {
                                    MarkerBean markerBean = new MarkerBean();
@@ -269,18 +368,22 @@
                                })
                                .collect(Collectors.toList());
                        DaoSingleton.getInstance(MapFragment.this.getContext()).markerDao().deleteAll();
                        // 使用 RxJava 异步插入数据
                        DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).markerDao().insertAll(markerBeans)
                                .subscribeOn(Schedulers.io()) // 在 IO 线程上执行
                                .observeOn(AndroidSchedulers.mainThread()) // 在主线程上观察
                                .subscribe(() -> {
                                    // 插入成功
                                    Log.i("mWebView", "数据插入成功");
                                }, throwable -> {
                                    // 插入失败
                                    Log.e("mWebView", "数据插入失败: " + throwable.getMessage());
                                });
                        // 使用 CompositeDisposable 管理数据库插入操作
                        compositeDisposable.add(
                            DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).markerDao().insertAll(markerBeans)
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(
                                    () -> {
                                        // 插入成功
                                        Log.i("mWebView", "数据插入成功");
                                    },
                                    throwable -> {
                                        // 插入失败
                                        Log.e("mWebView", "数据插入失败: " + throwable.getMessage());
                                    }
                                )
                        );
                    }
                } else {
@@ -297,7 +400,11 @@
        //巡检按钮
        binding.inspectButton.setOnClickListener(v -> {
            if (XXPermissions.isGranted(MapFragment.this.getContext(), Permission.ACCESS_BACKGROUND_LOCATION)) {
                chageInspecState(InspectionUtils.STAT_INSPECTION_ONCLICK);
                new ConfirmDialog(MapFragment.this.getActivity(), (confirmDialog, v1) -> {
                    chageInspecState(InspectionUtils.STAT_INSPECTION_ONCLICK);
                    confirmDialog.dismiss();
                }).show();
            } else {
                TipUtil.show(MapFragment.this.getActivity(), "巡检定位需要您选择\"始终允许\"定位信息,否则无法巡检。", new TipUtil.TipListener() {
                    @Override
@@ -343,6 +450,20 @@
    }
    /**
     * 显示分水房详情
     *
     * @param data
     */
    public void showDivideDetail(String data) {
        MyLog.i(data);
        DivideBean markerBean = divideBeanMap.get(data);
        if (markerBean != null) {
            binding.bottomLL.setVisibility(View.GONE);
            getDivideDetail(markerBean);
        }
    }
    /**
     * 获取地图中心点
@@ -572,6 +693,50 @@
        }
    }
    /**
     * 添加取水口标注
     */
    public void setMapDivide(DivideBean divide) {
        if (divide != null) {
            if (webViewIsFinished) {
                if (!TextUtils.isEmpty(divide.getLng()) && !TextUtils.isEmpty(divide.getLat())) {
                    mWebView.evaluateJavascript("javascript:addDivide(\"" + divide.getId() + "\",\"" + divide.getLng() + "\",\"" + divide.getLat() + "\",\"" + divide.getDivideName() + "\")", new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String value) {
                        }
                    });
                    divideBeanMap.put(divide.getId(), divide);
                } else {
                    MyLog.d("setMapDivide>" + divide.getDivideName() + "经纬度为空");
                }
            } else {
                webNoFinishDivideData.add(divide);
            }
        }
    }
    /**
     * 添加管网标注
     */
    public void setMapDivide(PipeNetworkBean pipeNetworkBean) {
//        if (divide != null) {
//            if (webViewIsFinished) {
//                for ()
//                if (!TextUtils.isEmpty(divide.getLng()) && !TextUtils.isEmpty(divide.getLat())) {
//                    mWebView.evaluateJavascript("javascript:addDivide(\"" + divide.getId() + "\",\"" + divide.getLng() + "\",\"" + divide.getLat() + "\",\"" + divide.getDivideName() + "\")", new ValueCallback<String>() {
//                        @Override
//                        public void onReceiveValue(String value) {
//                        }
//                    });
//                    divideBeanMap.put(divide.getId(), divide);
//                } else {
//                    MyLog.d("setMapDivide>" + divide.getDivideName() + "经纬度为空");
//                }
//            } else {
//                webNoFinishDivideData.add(divide);
//            }
//        }
    }
    /**
     * 开始巡检的相关逻辑
@@ -667,6 +832,8 @@
                        });
                        binding.pointCenterImg.setVisibility(View.GONE);
                        binding.pointRL.setVisibility(View.GONE);
                        mMarkerBean.setLat(lat);
                        mMarkerBean.setLng(lng);
                        binding.lng.setText(lng);
                        binding.lat.setText(lat);
                        mWebView.evaluateJavascript("javascript:cancelPin()", value -> {
@@ -698,20 +865,20 @@
            public void onNext(BaseResponse<MarkerResult> t) {
                if (t.isSuccess()) {
                    MarkerResult result = t.getContent();
                    MarkerBean markerBean = new MarkerBean();
                    markerBean.setId(result.getId());
                    markerBean.setLng(result.getLng());
                    markerBean.setLat(result.getLat());
                    markerBean.setBlockId(result.getBlockId());
                    markerBean.setName(result.getName());
                    markerBean.setRemarks(result.getRemarks());
                    markerBean.setTownId(result.getTownId());
                    markerBean.setVillageId(result.getVillageId());
                    markerBean.setCountyId(result.getCountyId());
                    markerBean.setAddress(result.getAddress());
                    markerBean.setBlockName(result.getBlockName());
                    markerBean.setDivideId(result.getDivideId());
                    showMarker(markerBean);
                    mMarkerBean = new MarkerBean();
                    mMarkerBean.setId(result.getId());
                    mMarkerBean.setLng(result.getLng());
                    mMarkerBean.setLat(result.getLat());
                    mMarkerBean.setBlockId(result.getBlockId());
                    mMarkerBean.setName(result.getName());
                    mMarkerBean.setRemarks(result.getRemarks());
                    mMarkerBean.setTownId(result.getTownId());
                    mMarkerBean.setVillageId(result.getVillageId());
                    mMarkerBean.setCountyId(result.getCountyId());
                    mMarkerBean.setAddress(result.getAddress());
                    mMarkerBean.setBlockName(result.getBlockName());
                    mMarkerBean.setDivideId(result.getDivideId());
                    showMarker(mMarkerBean);
                } else {
                    ToastUtil.showToast(MapFragment.this.getContext(), t.getMsg());
                }
@@ -720,8 +887,32 @@
        });
    }
    /**
     * 显示取水口详情
     */
    private void getDivideDetail(DivideBean divideBean) {
        ApiManager.getInstance().requestGet(this.getContext(), Constants.BASE_URL + "/project/divide/getone/" + divideBean.getDivideId(), DivideResult.class, null, new SubscriberListener<BaseResponse<DivideResult>>() {
            @Override
            public void onNext(BaseResponse<DivideResult> t) {
                if (t.isSuccess()) {
                    DivideBean divideBean = getDivideBean(t.getContent());
                    showDivideMarker(divideBean);
                } else {
                    ToastUtil.showToast(MapFragment.this.getContext(), t.getMsg());
                }
            }
        });
    }
    /**
     * 显示取水口详情
     */
    private void showMarker(MarkerBean markerBean) {
        binding.bottomLL.setVisibility(View.VISIBLE);
        binding.phoneLL.setVisibility(View.GONE);
        binding.headerLL.setVisibility(View.GONE);
        binding.editePoint.setVisibility(View.VISIBLE);
        binding.markerAddress.setText(markerBean.getAddress());
        binding.markerName.setText(markerBean.getName());
        binding.markerBlockName.setText(markerBean.getBlockName());
@@ -756,10 +947,214 @@
        });
    }
    /**
     * 显示分水房详情
     *
     * @param divideBean
     */
    private void showDivideMarker(DivideBean divideBean) {
        binding.bottomLL.setVisibility(View.VISIBLE);
        binding.phoneLL.setVisibility(View.VISIBLE);
        binding.headerLL.setVisibility(View.VISIBLE);
        binding.editePoint.setVisibility(View.GONE);
        binding.markerAddress.setText(divideBean.getAddress());
        binding.markerName.setText(divideBean.getDivideName());
        binding.markerBlockName.setText(divideBean.getBlockName());
        binding.phone.setText(divideBean.getPhone());
        binding.header.setText(divideBean.getHeader());
        binding.lat.setText(divideBean.getLat());
        binding.lng.setText(divideBean.getLng());
        //修改经纬度
        binding.editePoint.setOnClickListener(v -> {
            mWebView.evaluateJavascript("javascript:showPin(\"" + divideBean.getLng() + "\",\"" + divideBean.getLat() + "\")", value -> {
                binding.pointRL.setVisibility(View.VISIBLE);
                binding.pointCenterImg.setVisibility(View.VISIBLE);
                MyLog.d("showPin>>" + value);
            });
        });
        //取消修改经纬度
        binding.pointCancel.setOnClickListener(v -> {
                    binding.pointCenterImg.setVisibility(View.GONE);
                    binding.pointRL.setVisibility(View.GONE);
                    mWebView.evaluateJavascript("javascript:cancelPin()", value -> {
                    });
                }
        );
        //确认修改经纬度
        binding.pointEdt.setOnClickListener(v -> {
            ConfirmDialog confirmDialog = new ConfirmDialog(MapFragment.this.getActivity(), "确认修改到该位置吗?", (confirmDialog1, v1) -> {
                confirmDialog1.dismiss();
//                updataInstake(markerBean);
            });
            confirmDialog.show();
        });
    }
    /**
     * 获取分水房
     */
    private void getDivideList() {
        ApiManager.getInstance().requestGetHideLoading(MapFragment.this.getContext(), BASE_URL + "/project/divide/getDivides", DivideListResult.class, null, new SubscriberListener<BaseResponse<DivideListResult>>() {
            @Override
            public void onNext(BaseResponse<DivideListResult> t) {
                try {
                    if (t.isSuccess()) {
                        if (t.getContent().getObj() != null && !t.getContent().getObj().isEmpty()) {
                            List<DivideBean> divideBeans = new ArrayList<>();
                            for (DivideResult divideResult : t.getContent().getObj()) {
                                DivideBean divideBean = getDivideBean(divideResult);
                                setMapDivide(divideBean);
                                divideBeans.add(divideBean);
                            }
                            // 使用 CompositeDisposable 管理数据库插入操作
                            compositeDisposable.add(
                                DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).divideDao().insertAll(divideBeans)
                                    .subscribeOn(Schedulers.io())
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .subscribe(
                                        () -> {
                                            // 插入成功
                                            Log.i("mWebView", "数据插入成功");
                                        },
                                        throwable -> {
                                            // 插入失败
                                            Log.e("mWebView", "数据插入失败: " + throwable.getMessage());
                                        }
                                    )
                            );
                        }
                    } else {
                        ToastUtil.showToastLong(MapFragment.this.getContext(), t.getMsg());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    CrashReport.postCatchedException(e);
                }
            }
        });
    }
    /**
     * 获取管网
     */
    private void getPipeNetworkList() {
        ApiManager.getInstance().requestGetHideLoading(MapFragment.this.getContext(), BASE_URL + "/project/network/all", PipeNetworkListResult.class, null, new SubscriberListener<BaseResponse<PipeNetworkListResult>>() {
            @Override
            public void onNext(BaseResponse<PipeNetworkListResult> t) {
                try {
                    if (t.isSuccess()) {
                        if (t.getContent().getObj() != null && !t.getContent().getObj().isEmpty()) {
                            List<DivideBean> divideBeans = new ArrayList<>();
                            for (PipeNetworkResult divideResult : t.getContent().getObj()) {
                                PipeNetworkBean divideBean = getPipeNetworkBean(divideResult);
                                setMapDivide(divideBean);
//                                divideBeans.add(divideBean);
                            }
                            // 使用 RxJava 异步插入数据
                            DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).divideDao().insertAll(divideBeans)
                                    .subscribeOn(Schedulers.io()) // 在 IO 线程上执行
                                    .observeOn(AndroidSchedulers.mainThread()) // 在主线程上观察
                                    .subscribe(() -> {
                                        // 插入成功
                                        Log.i("mWebView", "数据插入成功");
                                    }, throwable -> {
                                        // 插入失败
                                        Log.e("mWebView", "数据插入失败: " + throwable.getMessage());
                                    });
                        }
                    } else {
                        ToastUtil.showToastLong(MapFragment.this.getContext(), t.getMsg());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    CrashReport.postCatchedException(e);
                }
            }
        });
    }
    /**
     * @param divideResult
     * @return
     */
    private static @NonNull DivideBean getDivideBean(DivideResult divideResult) {
        DivideBean divideBean = new DivideBean();
        divideBean.setAddress(divideResult.getAddress());
        divideBean.setBlockId(divideResult.getBlockId());
        divideBean.setBlockName(divideResult.getBlockName());
        divideBean.setDivideId(divideResult.getDivideId());
        if (!TextUtils.isEmpty(divideResult.getDivideName())) {
            divideBean.setDivideName(divideResult.getDivideName());
        } else {
            divideBean.setDivideName(divideResult.getName());
        }
        divideBean.setHeader(divideResult.getHeader());
        divideBean.setId(divideResult.getId());
        divideBean.setLat(divideResult.getLat());
        divideBean.setLng(divideResult.getLng());
        divideBean.setOperateDt(divideResult.getOperateDt());
        divideBean.setOperator(divideResult.getOperator());
        divideBean.setPhone(divideResult.getPhone());
        divideBean.setRemarks(divideResult.getRemarks());
        divideBean.setVillages(divideResult.getVillages());
        divideBean.setArea(divideResult.getArea());
        return divideBean;
    }
    private static @NonNull PipeNetworkBean getPipeNetworkBean(PipeNetworkResult divideResult) {
        PipeNetworkBean pipeNetworkBean = new PipeNetworkBean();
        return pipeNetworkBean;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        // 清理所有订阅
        if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
            compositeDisposable.dispose();
        }
        LiveEventBus.get(CommonKeyName.locationData).removeObserver(locationObserver);
        if (mWebView != null) {
            mWebView.destroy();
        }
    }
    @Override
    public void onResume() {
        super.onResume();
        mWebView.onResume();
        mWebView.resumeTimers();
    }
    @Override
    public void onPause() {
        super.onPause();
        mWebView.onPause();
        mWebView.pauseTimers();
    }
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        mWebView.saveState(outState);
    }
    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        if (savedInstanceState != null) {
            mWebView.restoreState(savedInstanceState);
        }
    }
}