day 8-9 面試題:泛型、Android8.0適配

面試題:

1. 泛型:  
	1. 什麼是泛型,能解決什麼問題  
	2. 說說java中的泛型的工作機制  
	3. 在泛型中extends和super關鍵字的區別     
2. Android 8.0適配?

1. 面試題解題

1.1 泛型

1.1.1 什麼是泛型

泛型是Java SE1.5引入的,泛型本質是參數化類型,將所操作的數據類型指定爲一個參數,該參數類型可以用在類、接口、方法中。分別叫做泛型類、泛型接口、泛型方法。

  1. 泛型類

    泛型類用於類的定義中,比如List,Set,Map等。

     /**
      * 此處的T是泛型標識,可以是任意的大寫字母
      * 在調用時必須指定T的具體類型:new People<Integer>(60);
      */
     
     public class People<T> {
         private T t;
     
         public People(T t) {
             this.t = t;
         }
     }
    
  2. 泛型接口

    同泛型類一樣,用於接口的定義中,見下面的例子。

     public interface Age<T> {
         T getAge();
     }
    
     public class People implements Age<Integer>{
    
         @Override
         public Integer getAge() {
             return new Random().nextInt(100);
         }
     }
    
  3. 泛型方法

    需要在方法中使用的泛型如果沒有在類和接口中定義過,那麼必須在方法中定義後纔可使用。

     /**
      * public 和返回值E中間的類型申明是必需的,因爲只有申請了該類型,才能在方法中使用
      */
     public <E> E getInfomation(Class<E> eClass) throws IllegalAccessException, InstantiationException {
         E e = eClass.newInstance();
         return e;
     }
    

1.1.2 泛型能解決什麼問題

  1. 在編譯時檢查參數類型,避免異常發生
  2. 消除強制類型轉換
  3. 提高代碼複用率

1.1.3 說說java中的泛型的工作機制

Java泛型是編譯時技術,在運行時不包含泛型信息,僅僅是Class的實例中包含類型參數的定義信息。它是通過Java編譯器的擦除前端來實現的,可以認爲是從源碼到源碼的轉換,從泛型源碼轉爲非泛型的代碼。它有幾個特點:

  1. 不能依靠泛型做類型轉換
  2. 同一個泛型類,在被調用時類類型是一樣的,無論傳入的泛型類是否一樣

1.1.4 在泛型中extends和super關鍵字的區別

使用底下的例子來說明,extends是上界通配符,指定類的上邊界。它只能取,不能存,因爲你不清楚具體存的是哪個實現類,所以無法存入。
super是下界通配符,指定類的下邊界,它只能存,不能取,因爲根本不清楚取出的數據是什麼實現類,只能指定爲Object。

class Food{}
class Fruit extends Food{}

class Apple extends Fruit{}

class Banana extends Fruit{}

public void testExtends(List<? extends Fruit> fruits){
    // fruits.add(new Apple());
    Fruit fruit = fruits.get(0);
}

public void testSuper(List<? super Fruit> list){
    // Object object = list.get(0);
    list.add(new Fruit());
}

1.2 Android 8.0適配?

1.2.1 Android8.0 通知適配

Android 8.0加入了ChannelId和ChannelGroup的概念,如果在創建通知的時候不加ChannelId,通知是不會被喚起的。

  1. 創建小組,這個步驟可有可無

  2. 創建ChannelId(爲了簡單,都簡寫寫死,如果創建了小組,需要給ChannelId配置GroupId)

    NotificationChannel notificationChannel = new NotificationChannel("track_id", "track_name", NotificationManager.IMPORTANCE_LOW);
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.createNotificationChannel(notificationChannel);
    
  3. 在構建通知時,加入ChannelId(比以往多加一個參數ChannelId)

    Notification notification = new Notification.Builder(this, "track_id").build();
    

1.2.2 廣播限制

Android 8.0的應用無法在其清單文件中註冊隱式廣播接收器。

兩種方案:

  1. 動態註冊廣播
  2. 指定包名,作爲顯示廣播發送

1.2.3 後臺服務適配

Android 8.0 對應用在後臺執行的操作增加了限制,當應用處於後臺時,不允許再啓動服務。Android8.0提供了方法,在後臺可以創建前臺服務,下面看下步驟

  1. 啓動前臺服務

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
     	context.startForegroundService(service);
     }else{
     	context.startService(service);
     }
    
  2. 建立前臺服務通知並調用startForeground(1,notification)

    如果是IntentService,這部分邏輯需要加到onHandleIntent中,因爲onCreate並不是每次調用startService都會調用。

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
     	NotificationChannel notificationChannel = new NotificationChannel("track_id", "track_name", NotificationManager.IMPORTANCE_LOW);
     	NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
     	notificationManager.createNotificationChannel(notificationChannel);
     	Notification notification = new Notification.Builder(this, "track_id").build();
     	startForeground(1,notification);
     }
    
  3. 關閉前臺服務

     service.stopForeground(true);
    

1.2.4 apk安裝權限

Android 8.0 去除允許未知來源選項,需要用戶手動確認,如果沒有適配,覆蓋安裝時直接閃退。

  1. 最簡單的解決方式就是,在Manifest文件中配置請求安裝權限,這樣在app調用安裝界面時,系統會詢問用戶授權。

  2. 當然,你可以可以做的更復雜一些。

    1. 清單文件中配置REQUEST_INSTALL_PACKAGES權限

    2. 調用packageManager.canRequestPackageInstalls()獲取是否已有該權限

       PackageManager packageManager = getApplicationContext().getPackageManager();
       boolean canInstallApk = packageManager.canRequestPackageInstalls();
      
    3. 如果沒有權限,則彈框提示,點擊確定跳轉用戶授權頁面(一般更多的是使用startActivityForResult,授權完成繼續安裝)

       Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
       startActivity(intent);
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章