開(kāi)箱即用的Google與百度定位坐標(biāo)系轉(zhuǎn)換實(shí)例
集成谷歌定位與百度定位并在地圖上顯示
項(xiàng)目背景
東南亞某小國(guó)的App,需要用到定位與地圖顯示,我們都知道海外人士都是喜歡谷歌地圖與谷歌定位的,那么必然是要優(yōu)先使用谷歌定位的,但是中國(guó)手機(jī)賣的很好,部分中國(guó)手機(jī)的海外版是沒(méi)有谷歌服務(wù)的,那么我使用百度地圖進(jìn)行降級(jí)處理。
兩者使用的定位坐標(biāo)系不同,如果需要在谷歌地圖上展示百度定位,需要如何轉(zhuǎn)換呢?或者說(shuō)谷歌的定位如何在百度地圖上展示呢?
一. 集成谷歌定位
跟項(xiàng)目下的build.gradle
別的先不說(shuō),先把谷歌服務(wù)插件給引入
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8'
}
app模塊下的build.gradle最底部 應(yīng)用谷歌服務(wù)插件
apply plugin: 'com.google.gms.google-services'
然后去谷歌后臺(tái)申請(qǐng)App-Key相關(guān)的項(xiàng)目,需要填寫(xiě)包名和一些簽名文件的SHA1值,注意這里relese包的SHA1值,和谷歌市場(chǎng)上架的SHA1值是不同的,上架之后需要去谷歌市場(chǎng)把谷歌市場(chǎng)上的SHA1值設(shè)置進(jìn)去,因?yàn)楣雀枋袌?chǎng)上架之后會(huì)把你的簽名文件包裝一次,完全不同的簽名文件了。
完成此步之后 下載對(duì)應(yīng)App的 google-services.json 文件。
此步驟完成,我們?cè)龠h(yuǎn)程依賴谷歌定位的庫(kù)。location
//定位功能
api 'com.google.android.gms:play-services-location:16.0.0'
定位Api使用流程:
權(quán)限定義
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
注意使用之前要?jiǎng)討B(tài)申請(qǐng)權(quán)限,這里不做演示
//初始化谷歌地圖API
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
//Google-Location-Api 服務(wù)連接成功回調(diào)
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接成功了");
getAPILastLocation();
}
//Google-Location-Api 服務(wù)異常連接暫停
@Override
public void onConnectionSuspended(int i) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)被暫停了");
if (googleApiClient != null && !googleApiClient.isConnected())
googleApiClient.connect();
}
//Google-Location-Api 連接異常
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接錯(cuò)誤");
//如果連接錯(cuò)誤直接用百度定位
}
public void stopLocation() {
if (googleApiClient != null && googleApiClient.isConnected()){
googleApiClient.disconnect();
}
}
private void getAPILastLocation() {
FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mActivity);
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(mActivity, location -> {
if (location != null && location.getLatitude() > 0 && location.getLongitude() > 0) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.e("MapLastLocationUtils", "Google-API-獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
} else {
//如果沒(méi)有值直接用百度定位
}
});
}
二. 集成百度定位
我們也是需要在百度開(kāi)發(fā)者平臺(tái)上申請(qǐng)應(yīng)用的App,不過(guò)這一塊就比較簡(jiǎn)單,只需要驗(yàn)證包名就行了,然后會(huì)給你一個(gè)AppId。
我們下載定位的jar包與so動(dòng)態(tài)庫(kù),導(dǎo)入到項(xiàng)目,然后再清單文件配置
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="123456789">
</meta-data>
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
<intent-filter>
<action android:name="com.baidu.location.service_v2.2"></action>
</intent-filter>
</service>
Application中初始化SDK
SDKInitializer.initialize(context);
判斷開(kāi)啟谷歌定位還是百度定位的邏輯封裝
public class MapLastLocationUtils implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LifecycleObserver {
private static MapLastLocationUtils ourInstance;
private Activity mActivity;
private GoogleApiClient googleApiClient;
private LocationClient mBDLocationClient;
private LocationRequest mLocationRequest;
private boolean isNeedBackNotifyLocation = false;
public static MapLastLocationUtils getInstance(Activity context) {
if (ourInstance == null) {
ourInstance = new MapLastLocationUtils(context);
}
return ourInstance;
}
private MapLastLocationUtils(Activity context) {
mActivity = context;
//初始化谷歌地圖API
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
/**
* 只是獲取當(dāng)前的位置一次
*/
public void getLastLocation() {
int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(CommUtils.getContext());
if (code == ConnectionResult.SUCCESS) {
// 支持Google服務(wù)
getAPILastLocation();
} else {
//開(kāi)啟百度定位
getBDLastLocation();
}
}
//API連接成功嘗試獲取最后的位置
@SuppressLint("MissingPermission")
private void getAPILastLocation() {
FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mActivity);
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(mActivity, location -> {
if (location != null && location.getLatitude() > 0 && location.getLongitude() > 0) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.e("MapLastLocationUtils", "Google-API-獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
if (mListener != null) {
//這里轉(zhuǎn)換一下,如果國(guó)內(nèi)轉(zhuǎn)換為火星坐標(biāo),國(guó)外直接用
Gps gps = GPS84ToGCJ02(longitude, latitude);
mListener.onLastLocation(gps.getLatitude(), gps.getLongitude());
}
} else {
getBDLastLocation();
}
});
}
//百度定位嘗試獲取最后的位置
private void getBDLastLocation() {
mBDLocationClient = new LocationClient(mActivity);
//聲明LocationClient類
mBDLocationClient.registerLocationListener(mBDLastLocationListener);
//配置百度定位的選項(xiàng)
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy); // 可選,默認(rèn)高精度,設(shè)置定位模式,高精度,低功耗,僅設(shè)備
option.setCoorType("gcj02"); // 可選,默認(rèn)gcj02,設(shè)置返回的定位結(jié)果坐標(biāo)系,如果配合百度地圖使用,建議設(shè)置為bd09ll; 國(guó)際WGS84
option.setScanSpan(0); // 可選,默認(rèn)0,即僅定位一次,設(shè)置發(fā)起連續(xù)定位請(qǐng)求的間隔需要大于等于1000ms才是有效的
option.setIsNeedAddress(false); // 可選,設(shè)置是否需要地址信息,默認(rèn)不需要
option.setIsNeedLocationDescribe(false); // 可選,設(shè)置是否需要地址描述
option.setNeedDeviceDirect(false); // 可選,設(shè)置是否需要設(shè)備方向結(jié)果
option.setLocationNotify(false); // 可選,默認(rèn)false,設(shè)置是否當(dāng)gps有效時(shí)按照1S1次頻率輸出GPS結(jié)果
option.setIgnoreKillProcess(true); // 可選,默認(rèn)true,定位SDK內(nèi)部是一個(gè)SERVICE,并放到了獨(dú)立進(jìn)程,設(shè)置是否在stop
option.setIsNeedLocationDescribe(false); // 可選,默認(rèn)false,設(shè)置是否需要位置語(yǔ)義化結(jié)果,可以在BDLocation
option.setIsNeedLocationPoiList(false); // 可選,默認(rèn)false,設(shè)置是否需要POI結(jié)果,可以在BDLocation
option.SetIgnoreCacheException(false); // 可選,默認(rèn)false,設(shè)置是否收集CRASH信息,默認(rèn)收集
option.setOpenGps(false); // 可選,默認(rèn)false,設(shè)置是否開(kāi)啟Gps定位
option.setIsNeedAltitude(false); // 可選,默認(rèn)false,設(shè)置定位時(shí)是否需要海拔信息,默認(rèn)不需要,除基礎(chǔ)定位版本都可用
mBDLocationClient.setLocOption(option);
//開(kāi)啟定位
if (mBDLocationClient != null && !mBDLocationClient.isStarted()) {
mBDLocationClient.start();
}
}
//Google-Location-Api 服務(wù)連接成功回調(diào)
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接成功了");
getAPILastLocation();
}
//Google-Location-Api 服務(wù)異常連接暫停
@Override
public void onConnectionSuspended(int i) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)被暫停了");
if (googleApiClient != null && !googleApiClient.isConnected())
googleApiClient.connect();
}
//Google-Location-Api 連接異常
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接錯(cuò)誤");
//如果連接錯(cuò)誤直接用百度定位吧
getBDLastLocation();
}
/**
* 停止全部的定位
*/
public void stopLocation() {
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
if (mBDLocationClient != null) {
if (mBDLastLocationListener != null) {
mBDLocationClient.unRegisterLocationListener(mBDLastLocationListener);
}
YYLogUtils.w("定位stop了");
mBDLocationClient.stop();
}
}
private OnLocationCallbackListener mListener;
public void setOnLocationCallbackListener(OnLocationCallbackListener listener) {
mListener = listener;
}
public interface OnLocationCallbackListener {
void onLastLocation(double lat, double lon);
}
/**
* 百度的監(jiān)聽(tīng)回調(diào)(最后的地址)
*/
BDAbstractLocationListener mBDLastLocationListener = new BDAbstractLocationListener() {
//百度定位成功的展示
@Override
public void onReceiveLocation(BDLocation bdLocation) {
if (bdLocation != null && bdLocation.getLocType() != BDLocation.TypeServerError &&
!(bdLocation.getLatitude() + "").equals("4.9E-324") &&
!(bdLocation.getLongitude() + "").equals("4.9E-324")) {
double latitude = bdLocation.getLatitude(); //獲取緯度信息
double longitude = bdLocation.getLongitude(); //獲取經(jīng)度信息
Log.w("MapLastLocationUtils", "百度定位獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
//獲取到了最后的位置-直接回調(diào)
if (mListener != null) {
mListener.onLastLocation(latitude, longitude);
}
} else {
Log.e("MapLastLocationUtils", "百度定位-獲取位置失敗");
if (googleApiClient != null && !googleApiClient.isConnected()) {
googleApiClient.connect();
} else {
getAPILastLocation();
}
}
}
@Override
public void onConnectHotSpotMessage(String s, int i) {
super.onConnectHotSpotMessage(s, i);
}
//百度定位的錯(cuò)誤信息展示
@Override
public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) {
super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage);
int tag = 2;
StringBuffer sb = new StringBuffer(256);
sb.append("診斷結(jié)果: ");
if (locType == BDLocation.TypeNetWorkLocation) {
if (diagnosticType == 1) {
sb.append("網(wǎng)絡(luò)定位成功,沒(méi)有開(kāi)啟GPS,建議打開(kāi)GPS會(huì)更好");
sb.append("\n" + diagnosticMessage);
} else if (diagnosticType == 2) {
sb.append("網(wǎng)絡(luò)定位成功,沒(méi)有開(kāi)啟Wi-Fi,建議打開(kāi)Wi-Fi會(huì)更好");
sb.append("\n" + diagnosticMessage);
}
} else if (locType == BDLocation.TypeOffLineLocationFail) {
if (diagnosticType == 3) {
sb.append("定位失敗,請(qǐng)您檢查您的網(wǎng)絡(luò)狀態(tài)");
sb.append("\n" + diagnosticMessage);
}
} else if (locType == BDLocation.TypeCriteriaException) {
if (diagnosticType == 4) {
sb.append("定位失敗,無(wú)法獲取任何有效定位依據(jù)");
sb.append("\n" + diagnosticMessage);
} else if (diagnosticType == 5) {
sb.append("定位失敗,無(wú)法獲取有效定位依據(jù),請(qǐng)檢查運(yùn)營(yíng)商網(wǎng)絡(luò)或者Wi-Fi網(wǎng)絡(luò)是否正常開(kāi)啟,嘗試重新請(qǐng)求定位");
sb.append(diagnosticMessage);
} else if (diagnosticType == 6) {
sb.append("定位失敗,無(wú)法獲取有效定位依據(jù),請(qǐng)嘗試插入一張sim卡或打開(kāi)Wi-Fi重試");
sb.append("\n" + diagnosticMessage);
} else if (diagnosticType == 7) {
sb.append("定位失敗,飛行模式下無(wú)法獲取有效定位依據(jù),請(qǐng)關(guān)閉飛行模式重試");
sb.append("\n" + diagnosticMessage);
} else if (diagnosticType == 9) {
sb.append("定位失敗,無(wú)法獲取任何有效定位依據(jù)");
sb.append("\n" + diagnosticMessage);
}
} else if (locType == BDLocation.TypeServerError) {
if (diagnosticType == 8) {
sb.append("定位失敗,請(qǐng)確認(rèn)您定位的開(kāi)關(guān)打開(kāi)狀態(tài),是否賦予APP定位權(quán)限");
sb.append("\n" + diagnosticMessage);
}
}
Log.e("MapLastLocationUtils", sb.toString());
}
};
// ======================= update begin ↓ =========================
/**
* 開(kāi)啟后臺(tái)的通知欄定位
*/
public void startBackNotifyLocation() {
isNeedBackNotifyLocation = true;
if (mBDLocationClient == null) {
mBDLocationClient = new LocationClient(mActivity);
}
LocationClientOption mOption = new LocationClientOption();
mOption.setScanSpan(15000);
mOption.setIsNeedAddress(false);
mOption.setOpenGps(true);
mBDLocationClient.setLocOption(mOption);
// mClient.registerLocationListener(mBDUpdateLocationListener);
Notification notification;
if (Build.VERSION.SDK_INT >= 26) {
NotificationUtils mNotificationUtils = new NotificationUtils(mActivity);
Notification.Builder builder2 = mNotificationUtils.getAndroidChannelNotification("YY Circle", "Locating in the background");
builder2.setSmallIcon(R.drawable.ic_launcher_map);
notification = builder2.build();
} else {
//獲取一個(gè)Notification構(gòu)造器
Notification.Builder builder = new Notification.Builder(mActivity);
builder.setContentTitle("YY Circle") // 設(shè)置下拉列表里的標(biāo)題
.setSmallIcon(R.drawable.ic_launcher_map) // 設(shè)置狀態(tài)欄內(nèi)的小圖標(biāo)
.setContentText("Locating in the background") // 設(shè)置上下文內(nèi)容
.setWhen(System.currentTimeMillis()); // 設(shè)置該通知發(fā)生的時(shí)間
notification = builder.build(); // 獲取構(gòu)建好的Notification
}
notification.defaults = Notification.DEFAULT_SOUND; //設(shè)置為默認(rèn)的聲音
//開(kāi)啟前臺(tái)通知的后臺(tái)定位
mBDLocationClient.enableLocInForeground(1, notification);
mBDLocationClient.start();
}
// ======================= 轉(zhuǎn)換 begin ↓ =========================
private double pi = 3.1415926535897932384626;
private double a = 6378245.0;
private double ee = 0.00669342162296594323;
/**
* 國(guó)際 GPS84 坐標(biāo)系
* 轉(zhuǎn)換成
* [國(guó)測(cè)局坐標(biāo)系] 火星坐標(biāo)系 (GCJ-02)
* <p>
* World Geodetic System ==> Mars Geodetic System
*
* @param lon 經(jīng)度
* @param lat 緯度
* @return GPS實(shí)體類
*/
public Gps GPS84ToGCJ02(double lon, double lat) {
if (outOfChina(lat, lon)) {
YYLogUtils.e("GPS84ToGCJ02:國(guó)外的坐標(biāo)不做處理");
return new Gps(lon, lat);
} else {
YYLogUtils.e("GPS84ToGCJ02:處理國(guó)內(nèi)的坐標(biāo)");
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLon, mgLat);
}
}
/**
* [國(guó)測(cè)局坐標(biāo)系] 火星坐標(biāo)系 (GCJ-02)
* 轉(zhuǎn)換成
* 國(guó)際 GPS84 坐標(biāo)系
*
* @param lon 火星經(jīng)度
* @param lat 火星緯度
*/
public Gps GCJ02ToGPS84(double lon, double lat) {
Gps gps = transform(lon, lat);
double lontitude = lon * 2 - gps.getLongitude();
double latitude = lat * 2 - gps.getLatitude();
return new Gps(lontitude, latitude);
}
private Gps transform(double lon, double lat) {
if (outOfChina(lon, lat)) {
return new Gps(lon, lat);
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLon, mgLat);
}
/**
* 不在中國(guó)范圍內(nèi)
*
* @param lon 經(jīng)度
* @param lat 緯度
* @return boolean值
*/
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/**
* 緯度轉(zhuǎn)化算法
*
* @param x
* @param y
* @return
*/
private double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 經(jīng)度轉(zhuǎn)化算法
*
* @param x
* @param y
* @return
*/
private double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
}
三. 坐標(biāo)系轉(zhuǎn)換與地圖上的顯示
網(wǎng)上一搜坐標(biāo)系那可太多了,我們不整那么復(fù)雜,我們Android就知道2個(gè) gcj02(中國(guó)國(guó)測(cè)局) 和 wgs84(通過(guò)坐標(biāo)系) 。由于我們不是國(guó)內(nèi)的應(yīng)用,并且集成了非單一的定位軟件,所以我們就不知道私有的坐標(biāo)系如bd09之類的。
可以看到我們上面的工具類都是使用的gcj02坐標(biāo)系定位的,在中國(guó)就需要gcj02定位,這樣比較準(zhǔn)確,如果要在對(duì)應(yīng)的地圖上展示,則需要對(duì)應(yīng)的坐標(biāo)系經(jīng)緯度,在對(duì)應(yīng)的坐標(biāo)系地圖上展示。
如我們的定位是gcj02的坐標(biāo)系,在谷歌地圖上展示則需要轉(zhuǎn)換為wgs之后才對(duì),不然會(huì)有大概800米的誤差。百度地圖則可以設(shè)置坐標(biāo)系,設(shè)置為gcj02之后就可以在百度地圖上展示。
坐標(biāo)系的轉(zhuǎn)換工具類在上面就有了。
以上就是開(kāi)箱即用的Google與百度定位坐標(biāo)系轉(zhuǎn)換實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于Google 百度定位坐標(biāo)系轉(zhuǎn)換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android用于加載xml的LayoutInflater源碼超詳細(xì)分析
今天不想去聊一些Android的新功能,新特性之類的東西,特別想聊一聊這個(gè)老生常談的話題:LayoutInflater,感興趣的朋友來(lái)看看吧2022-08-08
Android小掛件(APP Widgets)設(shè)計(jì)指導(dǎo)
這篇文章主要為大家詳細(xì)介紹了Android小掛件APP Widgets設(shè)計(jì)指導(dǎo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
android?studio?項(xiàng)目?:UI設(shè)計(jì)高精度實(shí)現(xiàn)簡(jiǎn)單計(jì)算器
這篇文章主要介紹了android?studio?項(xiàng)目?:UI設(shè)計(jì)高精度實(shí)現(xiàn)簡(jiǎn)單計(jì)算器,自主完成一個(gè)簡(jiǎn)單APP的設(shè)計(jì)工作,綜合應(yīng)用已經(jīng)學(xué)到的Android?UI設(shè)計(jì)技巧,下面來(lái)看看實(shí)驗(yàn)實(shí)現(xiàn)過(guò)程2021-12-12
深入理解Android中的Handler異步通信機(jī)制
這篇文章主要介紹了Android中的Handler異步通信機(jī)制,文中舉了兩個(gè)例子介紹了Handler里面實(shí)用的API中的方法,需要的朋友可以參考下2016-03-03
Android?JetPack組件的支持庫(kù)Databinding詳解
DataBinding是Google發(fā)布的一個(gè)數(shù)據(jù)綁定框架,它能夠讓開(kāi)發(fā)者減少重復(fù)性非常高的代碼,如findViewById這樣的操作。其核心優(yōu)勢(shì)是解決了數(shù)據(jù)分解映射到各個(gè)view的問(wèn)題,在MVVM框架中,實(shí)現(xiàn)的View和Viewmode的雙向數(shù)據(jù)綁定2022-08-08
Android Studio kotlin生成編輯類注釋代碼
這篇文章主要介紹了Android Studio kotlin生成編輯類注釋代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Android Handler內(nèi)存泄漏詳解及其解決方案
在android開(kāi)發(fā)過(guò)程中,我們可能會(huì)遇到過(guò)令人奔潰的OOM異常,這篇文章主要介紹了Android Handler內(nèi)存泄漏詳解及其解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08

