国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

淺析Android位置權限以及數組尋找索引的坑

2019-10-21 21:45:24
字體:
來源:轉載
供稿:網友

一、Android 危險權限,來自官方文檔的坑

Android開發者都知道,Android 6.0 之前,權限申請只需要在 AndroidManifest.xml 文件中聲明就可以。Android 6.0 開始,權限申請發生了變化,危險權限需要在應用中動態申請,之前寫過一篇 Android 動態申請危險權限的筆記,詳情參考: Android 6.0 動態申請危險權限。

先截個圖,看看Android官方的說明:

Android,位置權限,數組,索引

再看危險權限的分組情況:

Android,位置權限,數組,索引

意思是,對危險權限進行了分組,同一組中,只要有有一個權限被授權了,同組中其它權限也就默認授權了。比如,我授權應用有讀存儲卡的權限之后,應用也就有了寫存儲卡的權限,事實上也確實如此。
然而問題來了,利用 GPS 獲取位置信息的代碼:

LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)  != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission  (MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)  != PackageManager.PERMISSION_GRANTED){ // request permissions // ... // ... }else{   Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER; if(location != null){   double latitude = location.getLatitude();   double longitude = location.getLongitude();  }  }}

通過官方的危險權限組,我們也能看到:Location 權限組里包含:ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 兩個權限,按照上面的說明,兩個權限只要有一個申請授權成功,即可成功獲取經緯度。——然鵝,當成功申請了 ACCESS_COARSE_LOCATION 權限后,程序依然會崩,錯誤信息提示,需要獲得 ACCESS_FINE_LOCATION 權限 。

二、Spinner 的 setSelection() 方法,源于自己想當然的坑

Android 中的下拉列表控件 spinner 有一個方法 setSelection(int position) ,顯示第幾項。此方法可能沒有效果???總是顯示第一項???

當在做兩個spinner聯動時,spinner2依據spinner1的選擇填充數據,然后使用setSeletion(2)來設置默認項。結果發現:spinner2顯示的總是第一項,但是實際選擇的確實已經是position 2的位置 。
解決方法:

舊代碼:

spinner.setAdapter(adapter);  spinner.setSelection(2);

解決方案有二:

(1)

spinner.setAdapter(adapter);  spinner.setSelection(2,true); //spinner會重新layout

(2) 推薦

 spinner.setAdapter(adapter);![](https://images2018.cnblogs.com/blog/758949/201807/758949-20180726224508174-131546620.jpg)  adapter.notifyDataSetChanged(); //通知spinner刷新數據 spinner.setSelection(2);

那么,這到底是什么原因造成的?我認為這是一個bug 。這種情況通常發生在重新填充數據之后,除此之外,使用setSelection(int position)都能得到正確的顯示。

setSelection(int position, boolean animate)和setSelection(int position) 實現機制有較大區別,當調用前者時重新layout,立即觸發onItemSelected函數,作用相當于用手直接點擊。而后者設置了下次選擇位置:setNextSelectedPositionInt(position); 然后請求Layout;,而requestLayout并非立即執行,僅僅是一個schedule。但是后者可能在重新裝載數據然后Layout時丟失了某些狀態。

然鵝,我要說的坑不是這樣,我沒有兩個 Spinner 聯動,我出現的問題是這樣的,上代碼

布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.sharpcj.helloworld.MainActivity"> <Spinner  android:id="@+id/sp_test"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_centerInParent="true"> </Spinner></RelativeLayout>

java 代碼:

package com.example.sharpcj.helloworld;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.Spinner;import java.util.Arrays;public class MainActivity extends AppCompatActivity { private Spinner mSpTest; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  String[] strs = new String[20];  for (int i = 0; i < strs.length; i++) {   strs[i] = "第" + i + "項";  }  mSpTest = findViewById(R.id.sp_test);  mSpTest.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, strs));  int index = Arrays.binarySearch(strs, "第11項");  mSpTest.setSelection(index); }}

運行結果:

Android,位置權限,數組,索引

what???
為什么會這樣呢? spinner 表示這個鍋它不背,其實這個坑怪我自己想當然了,原因在于錯誤地使用了 Arrays.binarySearch(Object[] a , Object key) 這個方法,想當然地認為了返回值為查找到數組的 index。代碼中, index 的實際值是 -2 。

網上找了一下資料:

binarySearch(int[] a, int key) 此方法的規則是這樣的:

1、如果找到關鍵字,則返回值為關鍵字在數組中的位置索引,且索引從0開始

2、如果沒有找到關鍵字,返回值為負的插入點值,所謂插入點值就是第一個比關鍵字大的元素在數組中的位置索引,而且這個位置索引從1開始。

而binarySearch(Object[] a, Object key) 最終調用方法的源碼如下:

 // Like public version, but without range checks. private static int binarySearch0(Object[] a, int fromIndex, int toIndex,          Object key) {  int low = fromIndex;  int high = toIndex - 1;  while (low <= high) {   int mid = (low + high) >>> 1;   @SuppressWarnings("rawtypes")   Comparable midVal = (Comparable)a[mid];   @SuppressWarnings("unchecked")   int cmp = midVal.compareTo(key);   if (cmp < 0)    low = mid + 1;   else if (cmp > 0)    high = mid - 1;   else    return mid; // key found  }  return -(low + 1); // key not found. }

關于 Object 類型,Oracle 大神寫的這個二分法尋找索引的代碼暫時沒看懂。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 建湖县| 会理县| 思南县| 金平| 双柏县| 台州市| 精河县| 丹寨县| 车致| 正镶白旗| 启东市| 秦安县| 汾西县| 穆棱市| 济阳县| 大安市| 通河县| 葫芦岛市| 五寨县| 睢宁县| 颍上县| 嘉黎县| 登封市| 四川省| 平遥县| 德昌县| 八宿县| 湘西| 阿瓦提县| 临海市| 大厂| 黑龙江省| 金山区| 时尚| 申扎县| 安义县| 姚安县| 玛沁县| 武义县| 东海县| 富川|