This commit is contained in:
wangcongtao
2020-01-05 16:24:07 +08:00
parent a0aa63b89b
commit 323376dcec
77 changed files with 2518 additions and 567 deletions

View File

@@ -0,0 +1,48 @@
package com.mogo.module.service;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 自动刷新策略
*/
public class AutoRefreshStrategy {
public static final long ONE_MINUTE = 5 * 1_000L;
/**
* 距离(米)
*/
private int distance = 2_000;
/**
* 时间间距s
*/
private long interval = 3 * ONE_MINUTE;
/**
* 用户打断后的延时s
*/
private long interruptInterval = 1 * ONE_MINUTE;
/**
* 距离(米)
*/
public int getDistance() {
return distance;
}
/**
* 时间间距s
*/
public long getInterval() {
return interval;
}
/**
* 用户打断后的延时
*/
public long getInterruptInterval() {
return interruptInterval;
}
}

View File

@@ -0,0 +1,19 @@
package com.mogo.module.service;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 手动刷新策略
*/
public class CustomRefreshStrategy {
/**
* 缩小倍数
*/
private float zoomOutLevel = 2;
public float getZoomOutLevel() {
return zoomOutLevel;
}
}

View File

@@ -1,148 +0,0 @@
package com.mogo.module.service;
import android.app.Service;
import android.content.Context;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.map.MogoLatLng;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.location.MogoLocation;
import com.mogo.map.model.MogoPoi;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.map.navi.MogoNaviInfo;
import com.mogo.map.uicontroller.EnumMapUI;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.utils.logger.Logger;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 数据刷新策略
*/
@Route( path = ServiceConst.PATH_REFRESH_STRATEGY )
public class MogoRefreshStrategyProvider implements IMogoModuleProvider, IMogoMapListener, IMogoLocationListener, IMogoNaviListener {
private static final String TAG = "MogoRefreshStrategyProvider";
@Override
public final Fragment createFragment( Context context, Bundle data ) {
return null;
}
@Override
public final View createView( Context context ) {
return null;
}
@Override
public final IMogoModuleLifecycle getCardLifecycle() {
return null;
}
@Override
public IMogoMapListener getMapListener() {
return this;
}
@Override
public int getType() {
return TYPE_SERVICE;
}
@Override
public IMogoNaviListener getNaviListener() {
return this;
}
@Override
public IMogoLocationListener getLocationListener() {
return this;
}
@NonNull
@Override
public String getModuleName() {
return ServiceConst.PATH_REFRESH_STRATEGY;
}
@Override
public void init( Context context ) {
}
@Override
public void onMapLoaded() {
}
@Override
public void onTouch( MotionEvent motionEvent ) {
}
@Override
public void onPOIClick( MogoPoi poi ) {
}
@Override
public void onMapClick( MogoLatLng latLng ) {
}
@Override
public void onLockMap( boolean isLock ) {
}
@Override
public void onMapModeChanged( EnumMapUI ui ) {
}
@Override
public void onMapChanged( MogoLatLng latLng, float zoom, float tilt, float bearing ) {
Logger.d( TAG, "current map status: %s, zoom = %f, tilt = %f, bearing = %f", latLng, zoom, tilt, bearing );
}
@Override
public void onLocationChanged( MogoLocation location ) {
}
@Override
public void onInitNaviFailure() {
}
@Override
public void onInitNaviSuccess() {
}
@Override
public void onNaviInfoUpdate( MogoNaviInfo naviinfo ) {
}
@Override
public void onStartNavi() {
}
@Override
public void onStopNavi() {
}
}

View File

@@ -0,0 +1,431 @@
package com.mogo.module.service;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.map.MogoLatLng;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.location.MogoLocation;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerManager;
import com.mogo.map.marker.MogoMarkerOptions;
import com.mogo.map.model.MogoPoi;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.map.navi.MogoNaviInfo;
import com.mogo.map.uicontroller.EnumMapUI;
import com.mogo.map.uicontroller.IMogoMapUIController;
import com.mogo.module.service.network.RefreshCallback;
import com.mogo.module.service.network.RefreshModel;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.map.IMogoMapService;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.service.module.ModuleType;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
import com.mogo.service.statusmanager.IMogoStatusManager;
import com.mogo.service.statusmanager.StatusDescriptor;
import com.mogo.utils.logger.Logger;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 数据刷新策略
*/
@Route( path = ServiceConst.PATH_REFRESH_STRATEGY )
public class MogoServiceProvider implements IMogoModuleProvider,
IMogoMapListener,
IMogoLocationListener,
IMogoNaviListener,
IMogoStatusChangedListener {
private static final String TAG = "MogoRefreshStrategyProvider";
/**
* 自动刷新策略
*/
private AutoRefreshStrategy mAutoRefreshStrategy = new AutoRefreshStrategy();
private MogoLatLng mLastAutoRefreshLocation = null;
private long mLastRefreshTime = 0;
private IMogoMarkerManager mMarkerManager;
private IMogoMapUIController mUiController;
/**
* 是否已计算出地图显示状态
*/
private boolean mIsMapStatusOk = false;
/**
* 地图显示是横屏还是竖屏:根据地图右上角和左下角坐标计算
*/
boolean mIsVertical = false;
/**
* 手动刷新策略
*/
private CustomRefreshStrategy mCustomRefreshStrategy = new CustomRefreshStrategy();
private float mLastZoomLevel = 0;
private RefreshModel mRefreshModel;
private long mRefreshRemainingTime = Long.MAX_VALUE;
// 上次手动操作的中心点坐标
private MogoLatLng mLastCustomRefreshCenterLocation;
private IMogoMapService mMogoMapService;
private IMogoMarker mCameraCenterMarker = null;
private IMogoStatusManager mStatusManager;
/**
* 地图视图初始化
*/
private boolean mIsCameraInited = true;
private Handler mHandler = new Handler( Looper.getMainLooper() ) {
@Override
public void handleMessage( @NonNull Message msg ) {
super.handleMessage( msg );
switch ( msg.what ) {
case ServiceConst.MSG_TYPE_REFRESH_DECREASE:
mRefreshRemainingTime -= ServiceConst.DECREASE_INTERVAL;
if ( mRefreshRemainingTime == 0 ) {
notifyRefreshData( mAutoRefreshCallback );
} else {
mHandler.sendEmptyMessageDelayed( msg.what, ServiceConst.DECREASE_INTERVAL );
}
break;
}
}
};
private Context mContext;
/**
* 地图视图西南角坐标
*/
private MogoLatLng mCameraSouthWestPosition;
/**
* 地图视图东北角坐标
*/
private MogoLatLng mCameraNorthEastPosition;
/**
* 手动刷新回调
*/
private RefreshCallback mCustomRefreshCallback = new RefreshCallback() {
@Override
public void onSuccess() {
// 用户手动操作地图刷新成功后,设置状态为 true引发延时策略
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, true, true );
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, false, false );
}
@Override
public void onFail() {
}
};
/**
* 自动刷新回调
*/
private RefreshCallback mAutoRefreshCallback = new RefreshCallback() {
@Override
public void onSuccess() {
invokeAutoRefreshStrategy();
}
@Override
public void onFail() {
invokeAutoRefreshStrategy();
}
private void invokeAutoRefreshStrategy() {
mRefreshRemainingTime = mAutoRefreshStrategy.getInterval();
mHandler.removeMessages( ServiceConst.MSG_TYPE_REFRESH_DECREASE );
mHandler.sendEmptyMessageDelayed( ServiceConst.MSG_TYPE_REFRESH_DECREASE, ServiceConst.DECREASE_INTERVAL );
}
};
@Override
public final Fragment createFragment( Context context, Bundle data ) {
return null;
}
@Override
public final View createView( Context context ) {
return null;
}
@Override
public final IMogoModuleLifecycle getCardLifecycle() {
return null;
}
@Override
public IMogoMapListener getMapListener() {
return this;
}
@Override
public int getType() {
return ModuleType.TYPE_SERVICE;
}
@Override
public IMogoNaviListener getNaviListener() {
return this;
}
@Override
public IMogoLocationListener getLocationListener() {
return this;
}
@NonNull
@Override
public String getModuleName() {
return ServiceConst.TYPE;
}
@Override
public void init( Context context ) {
mContext = context;
mRefreshModel = new RefreshModel( context );
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation( context );
mMarkerManager = mMogoMapService.getMarkerManager( context );
mUiController = mMogoMapService.getMapUIController();
mStatusManager = ( IMogoStatusManager ) ARouter.getInstance().build( MogoServicePaths.PATH_STATUS_MANAGER ).navigation( context );
mStatusManager.registerStatusChangedListener( ServiceConst.TYPE, StatusDescriptor.USER_INTERACTED, this );
}
@Override
public void onMapLoaded() {
refreshCameraPosition();
}
private void initMapStatus() {
if ( mIsMapStatusOk ) {
return;
}
try {
float width = getMapCameraFactWidth();
float height = getMapCameraFactHeight();
mIsVertical = width < height;
Logger.i( TAG, "map status is vertical : " + mIsVertical );
mIsMapStatusOk = true;
} catch ( Exception e ) {
}
}
/**
* 地图视图对应的实际宽度
*
* @return
*/
private float getMapCameraFactWidth() {
return Utils.calculateLineDistance( mCameraNorthEastPosition, new MogoLatLng( mCameraNorthEastPosition.lat, mCameraSouthWestPosition.lng ) );
}
/**
* 地图视图对应的实际高度
*
* @return
*/
private float getMapCameraFactHeight() {
return Utils.calculateLineDistance( mCameraSouthWestPosition, new MogoLatLng( mCameraNorthEastPosition.lat, mCameraSouthWestPosition.lng ) );
}
/**
* 刷新视图范围坐标
*/
private void refreshCameraPosition() {
mCameraSouthWestPosition = mUiController.getCameraSouthWestPosition();
mCameraNorthEastPosition = mUiController.getCameraNorthEastPosition();
initMapStatus();
if ( mIsVertical ) {
float width = getMapCameraFactWidth();
Logger.i( TAG, "current zoom level width: %f m", width );
} else {
float height = getMapCameraFactHeight();
Logger.i( TAG, "current zoom level height: %f m", height );
}
}
@Override
public void onTouch( MotionEvent motionEvent ) {
switch ( motionEvent.getActionMasked() ) {
case MotionEvent.ACTION_DOWN:
if ( mLastZoomLevel == 0 ) {
mLastZoomLevel = mUiController.getZoomLevel();
Logger.i( TAG, "初始化缩放级别 为:%f", mLastZoomLevel );
}
break;
case MotionEvent.ACTION_UP:
break;
}
}
private void stopAutoRefreshStrategy() {
mHandler.removeMessages( ServiceConst.MSG_TYPE_REFRESH_DECREASE );
}
@Override
public void onPOIClick( MogoPoi poi ) {
}
@Override
public void onMapClick( MogoLatLng latLng ) {
}
@Override
public void onLockMap( boolean isLock ) {
}
@Override
public void onMapModeChanged( EnumMapUI ui ) {
}
@Override
public void onMapChanged( MogoLatLng latLng, float zoom, float tilt, float bearing ) {
if ( mIsCameraInited ) {
mLastCustomRefreshCenterLocation = latLng;
mIsCameraInited = false;
return;
}
if ( mCameraCenterMarker == null ) {
mCameraCenterMarker = mMarkerManager.addMarker( ServiceConst.TYPE,
new MogoMarkerOptions()
.icon( BitmapFactory.decodeResource( mContext.getResources(), R.drawable.ic_search_poi_location ) )
.latitude( latLng.lat )
.longitude( latLng.lng )
.owner( ServiceConst.TYPE )
);
} else {
mCameraCenterMarker.setPosition( latLng.lat, latLng.lng );
}
if ( mLastZoomLevel != zoom ) {
refreshCameraPosition();
}
// 手动刷新触发
if ( mLastZoomLevel - zoom > mCustomRefreshStrategy.getZoomOutLevel() ) {
// 缩放级别缩小
notifyRefreshData( mCustomRefreshCallback );
mLastCustomRefreshCenterLocation = latLng;
mLastZoomLevel = zoom;
} else if ( mLastZoomLevel == zoom ) {
// 手动平移
if ( invokeRefreshWhenTranslationByUser( latLng ) ) {
notifyRefreshData( mCustomRefreshCallback );
mLastCustomRefreshCenterLocation = latLng;
}
}
Logger.d( TAG, "current map status: %s, zoom = %f, tilt = %f, bearing = %f", latLng, zoom, tilt, bearing );
}
/**
* 平移地图刷新策略
*
* @return
*/
private boolean invokeRefreshWhenTranslationByUser( MogoLatLng latLng ) {
try {
float factor = 0.0f;
if ( mIsVertical ) {
factor = getMapCameraFactWidth();
} else {
factor = getMapCameraFactHeight();
}
if ( factor == 0.0f ) {
return false;
}
float distance = Utils.calculateLineDistance( latLng, mLastCustomRefreshCenterLocation );
return distance > factor;
} catch ( Exception e ) {
Logger.w( TAG, "warming. ", e );
return false;
}
}
@Override
public void onLocationChanged( MogoLocation location ) {
if ( location == null ) {
return;
}
// 自动刷新触发
if ( mLastAutoRefreshLocation == null ) {
mLastAutoRefreshLocation = new MogoLatLng( location.getLatitude(), location.getLongitude() );
notifyRefreshData( mAutoRefreshCallback );
} else {
float distance = Utils.calculateLineDistance( mLastAutoRefreshLocation, new MogoLatLng( location.getLatitude(), location.getLongitude() ) );
if ( distance > mAutoRefreshStrategy.getDistance() ) {
notifyRefreshData( mAutoRefreshCallback );
}
}
}
/**
* 刷新数据
*/
private void notifyRefreshData( RefreshCallback callback ) {
Logger.d( TAG, mAutoRefreshCallback == callback ? "触发自动刷新" : "触发手动刷新" );
mRefreshModel.refreshData( callback );
}
@Override
public void onInitNaviFailure() {
}
@Override
public void onInitNaviSuccess() {
}
@Override
public void onNaviInfoUpdate( MogoNaviInfo naviinfo ) {
}
@Override
public void onStartNavi() {
}
@Override
public void onStopNavi() {
}
@Override
public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
if ( descriptor == StatusDescriptor.USER_INTERACTED && isTrue ) {
Logger.i( TAG, "用户状态改变,自动刷新时间延时" );
mRefreshRemainingTime += mAutoRefreshStrategy.getInterruptInterval();
}
}
}

View File

@@ -8,8 +8,22 @@ package com.mogo.module.service;
*/
public class ServiceConst {
/**
* 类型
*/
public static final String TYPE = "STRATEGY_REFRESH";
/**
* 刷新策略模块地址
*/
public static final String PATH_REFRESH_STRATEGY = "/strategy/refresh";
/**
* 倒计时消息
*/
public static final int MSG_TYPE_REFRESH_DECREASE = 0x100;
/**
* 倒计时间隔
*/
public static final int DECREASE_INTERVAL = 1_000;
}

View File

@@ -0,0 +1,51 @@
package com.mogo.module.service;
import com.amap.api.maps.AMapException;
import com.amap.api.maps.model.LatLng;
import com.mogo.map.MogoLatLng;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 描述
*/
public class Utils {
public static float calculateLineDistance( MogoLatLng point1, MogoLatLng point2 ) {
if ( point1 != null && point2 != null ) {
try {
double var2 = point1.lng;
double var4 = point1.lat;
double var6 = point2.lng;
double var8 = point2.lat;
var2 *= 0.01745329251994329D;
var4 *= 0.01745329251994329D;
var6 *= 0.01745329251994329D;
var8 *= 0.01745329251994329D;
double var10 = Math.sin( var2 );
double var12 = Math.sin( var4 );
double var14 = Math.cos( var2 );
double var16 = Math.cos( var4 );
double var18 = Math.sin( var6 );
double var20 = Math.sin( var8 );
double var22 = Math.cos( var6 );
double var24 = Math.cos( var8 );
double[] var28 = new double[3];
double[] var29 = new double[3];
var28[0] = var16 * var14;
var28[1] = var16 * var10;
var28[2] = var12;
var29[0] = var24 * var22;
var29[1] = var24 * var18;
var29[2] = var20;
return ( float ) ( Math.asin( Math.sqrt( ( var28[0] - var29[0] ) * ( var28[0] - var29[0] ) + ( var28[1] - var29[1] ) * ( var28[1] - var29[1] ) + ( var28[2] - var29[2] ) * ( var28[2] - var29[2] ) ) / 2.0D ) * 1.27420015798544E7D );
} catch ( Throwable var26 ) {
var26.printStackTrace();
return 0.0F;
}
} else {
return 0.0F;
}
}
}

View File

@@ -0,0 +1,22 @@
package com.mogo.module.service.network;
import com.mogo.commons.data.BaseData;
import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.Single;
import retrofit2.http.GET;
import retrofit2.http.QueryMap;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 接口描述
*/
public interface RefreshApiService {
@GET( "" )
Observable< BaseData > refreshData( @QueryMap Map< String, Object > params );
}

View File

@@ -0,0 +1,14 @@
package com.mogo.module.service.network;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 刷新回调
*/
public interface RefreshCallback {
void onSuccess();
void onFail();
}

View File

@@ -0,0 +1,65 @@
package com.mogo.module.service.network;
import android.content.Context;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.commons.data.BaseData;
import com.mogo.commons.network.ParamsProvider;
import com.mogo.commons.network.SubscribeImpl;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.network.IMogoNetwork;
import com.mogo.utils.network.RequestOptions;
import java.util.Map;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* @author congtaowang
* @since 2020-01-03
* <p>
* 刷新数据
*/
public class RefreshModel {
private final Context mContext;
private RefreshApiService mRefreshApiService;
public RefreshModel( Context context ) {
this.mContext = context;
IMogoNetwork network = ( IMogoNetwork ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_NETWORK ).navigation( context );
this.mRefreshApiService = network.create( RefreshApiService.class, "http://www.baidu.com/" );
}
public void refreshData( final RefreshCallback callback ) {
if ( callback != null ) {
callback.onSuccess();
return;
}
if ( mRefreshApiService != null ) {
final Map< String, Object > params = new ParamsProvider.Builder( mContext ).build();
mRefreshApiService.refreshData( params )
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe( new SubscribeImpl< BaseData >( RequestOptions.create( mContext ) ) {
@Override
public void onSuccess( BaseData o ) {
super.onSuccess( o );
if ( callback != null ) {
callback.onSuccess();
}
}
@Override
public void onError( String message, int code ) {
super.onError( message, code );
if ( callback != null ) {
callback.onFail();
}
}
} );
}
}
}