Android完整詳細阿里騰訊面試題含答案(一)

一、四大組件是什麼?

Activity【活動】:用於表現功能。java

Service【服務】:後臺運行服務,不提供界面呈現。android

BroadcastReceiver【廣播接收器】:用來接收廣播。web

Content Provider【內容提供商】:支持在多個應用中存儲和讀取數據,至關於數據庫。面試

二、四個組件的生命週期?

Activity生命週期圖
Fragment生命週期圖

Service的生命週期:首先Service有兩種啓動方式,而在這兩種啓動方式下,它的生命週期不一樣。數據庫

經過startService()方法啓動的服務瀏覽器

初始化結束後系統會調用 void onStart(Intent intent) 方法,用於處理傳遞給startService()的Intent對象。如音樂服務會打開Intent 來探明將要播放哪首音樂,並開始播放。注意:屢次調用startService()方法會屢次觸發onStart()方法。緩存

經過bindService ()方法啓動的服務安全

初始化結束後系統會調用 IBinder onBind(Intent intent) 方法,用來綁定傳遞給bindService 的Intent 的對象。注意:屢次調用bindService()時,若是該服務已啓動則不會再觸發此方法。性能優化

三、Activity的四種啓動模式對比?

  • Standard:標準的啓動模式,若是須要啓動一個activity就會建立該activity的實例。也是activity的默認啓動模式。
  • SingeTop:若是啓動的activity已經位於棧頂,那麼就不會從新建立一個新的activity實例。而是複用位於棧頂的activity實例對象。若是不位於棧頂仍舊會從新建立activity的實例對象。
  • SingleTask:設置了singleTask啓動模式的activity在啓動時,若是位於activity棧中,就會複用該activity,這樣的話,在該實例之上的全部activity都依次進行出棧操做,即執行對應的onDestroy()方法,直到當前要啓動的activity位於棧頂。通常應用在網頁的圖集,一鍵退出當前的應用程序。
  • singleInstance:若是使用singleInstance啓動模式的activity在啓動的時候會複用已經存在的activity實例。無論這個activity的實例是位於哪個應用當中,都會共享已經啓動的activity的實例對象。使用了singlestance的啓動模式的activity會單獨的開啓一個共享棧,這個棧中只存在當前的activity實例對象。

四、Activity在有Dialog時按Home鍵的生命週期?

當咱們的Activity上彈出Dialog對話框時,程序的生命週期依然是onCreate() ---> onStart() ---> onResume(),在彈出Dialog的時候並無onPause()和onStop()方法。而在此時咱們按下Home鍵,纔會繼續執行onPause()和onStop()方法。這說明對話框並無使Activity進入後臺,而是在點擊了Home鍵後Activity才進入後臺工做。bash

緣由就是,其實Dialog是Activity的一個組件,此時Activity並非不可見,而是被Dialog組件覆蓋了其餘的組件,此時咱們沒法對其餘組件進行操做而已。

五、兩個Activity 之間跳轉時必然會執行的是哪幾個方法?

首先定義兩個Activity,分別爲A和B。

當咱們在A中激活B時,A調用onPause()方法,此時B出如今屏幕時,B調用onCreate()、onStart()、onResume()。

這個時候B【B不是一個透明的窗體或對話框的形式】已經覆蓋了A的窗體,A會調用onStop()方法。

六、 前臺切換到後臺,而後再回到前臺,Activity生命週期回調方法。彈出Dialog,生命值週期回調方法?

首先定義兩個Activity,分別爲A和B。

完整順序爲:A調用onCreate()方法 ---> onStart()方法 ---> onResume()方法。當A啓動B時,A調用onPause()方法,而後調用新的Activity B,此時調用onCreate()方法 ---> onStart()方法 ---> onResume()方法將新Activity激活。以後A再調用onStop()方法。當A再次回到前臺時,B調用onPause()方法,A調用onRestart()方法 ---> onStart()方法 ---> onResume()方法,最後調用B的onStop()方法 ---> onDestory()方法。

彈出Dialog時,調用onCreate()方法 ---> onStart()方法 ---> onResume()方法。

七、fragment各類狀況下的生命週期?

因爲Fragment的生命週期與Activity的生命週期有着牽扯,因此把二者的圖放到一塊兒做爲對比理解。

接下來就不一樣狀況下的Fragment生命週期作一簡單介紹:

Fragment在Activity中replace

新替換的Activity:onAttach() ---> onCreate() ---> onCreatView() ---> onViewCreated ---> onActivityCreated() ---> onStart --->onResume()

被替換的Activity:onPause() ---> onStop() ---> onDestoryView() ---> onDestory() ---> onDetach()

Fragment在Activity中replace,並addToBackStack

新替換的Fragment(沒有在BackStack中):onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

新替換的Fragment(已經在BackStack中):onCreateView > onViewCreated > onActivityCreated > onStart > onResume

被替換的Fragment:onPause > onStop > onDestroyView

Fragment在ViewPager中切換

咱們稱切換前的的Fragment稱爲PreviousFragment,簡稱PF;切換後的Fragment稱爲NextFragment,簡稱NF;其餘Fragment稱爲OtherFragment,簡稱OF。

(在ViewPager中setUserVisibleHint能反映出Fragment是否被切換到後臺或前臺,因此在這裏也看成生命週期)

  • 若是相關的Fragment沒有被加載過:

NF: setUserVisibleHint(false)【用戶不可見】 > onAttach > onCreate > setUserVisibleHint(true)【用戶可見】 > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF跟NF相鄰: setUserVisibleHint(false) > onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

  • 若是相關的Fragment已經被加載過:

NF跟PF相鄰 :setUserVisibleHint(true)

NF跟PF不相鄰:setUserVisibleHint(true) > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相鄰 :setUserVisibleHint(false)

PF跟NF不相鄰:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相鄰:onPause > onStop > onDestroyView

OF跟NF相鄰:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夾在PF和NF中間:不調用任何生命週期方法

NF跟PF相鄰 :setUserVisibleHint(true)

NF跟PF不相鄰:setUserVisibleHint(true) > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相鄰 :setUserVisibleHint(false)

PF跟NF不相鄰:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相鄰:onPause > onStop > onDestroyView

OF跟NF相鄰:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夾在PF和NF中間:不調用任何生命週期方法

  • 若是重寫了FragmentPagerAdapter的DestroyItem方法,而且相關的Fragment已經加載過:

相互切換時只會調用setUserVisibleHint

Fragment進入了運行狀態:

Fragment在進入運行狀態時,如下四個生命週期會隨它所屬的Activity一塊兒被調用:

onPause() ---> onStop() ---> onStart() ---> onResume()

關於Fragment的onActivityResult方法:

使用Fragment的startActivity方法時,FragmentActivity的onActivityResult方法會回調相應的Fragment的onActivityResult方法,因此在重寫FragmentActivity的onActivityResult方法時,注意調用super.onActivityResult。

八、 如何實現Fragment的滑動?

將Fragment與viewpager綁定,經過viewpager中的touch事件,會進行move事件的滑動處理。

Fragment佈局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light">
 
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment One" />
</LinearLayout>
複製代碼
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light">
 
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment Two" />
</LinearLayout>
複製代碼

Fragment代碼:

public class FragmentOne extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
       return inflater.inflate(R.layout.fragment_one, container, false);
    }
}
複製代碼
public class FragmentTwo extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
       return inflater.inflate(R.layout.fragment_Two, container, false);
    }
}
複製代碼

viewpager佈局:

xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.spreadtrumshitaoli.fragmentscroll.MainActivity">
 
    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_height="match_parent"
        android:layout_width="match_parent"/>
 
</android.support.constraint.ConstraintLayout>
複製代碼

MainActivity代碼:

public class MainActivity extends AppCompatActivity {
 
    private FragmentOne fragmentOne;
    private FragmentTwo fragmentTwo;
 
    private ViewPager viewPager;
 
    private ArrayList<Fragment> mFragmentList = new ArrayList <Fragment>();
    private FragmentPagerAdapter fragmentPagerAdapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        init();
 
    }
 
    private void init() {
 
        viewPager = (ViewPager) findViewById(R.id.view_pager);
        fragmentOne = new FragmentOne();
        fragmentTwo = new FragmentTwo();
 
        mFragmentList.add(fragmentOne);
        mFragmentList.add(fragmentTwo);
 
//將adapter和fragment綁定在一塊兒。
        fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int i) {
                return mFragmentList != null ? mFragmentList.get(i) : null;
            }
 
            @Override
            public int getCount() {
                return mFragmentList != null ? mFragmentList.size() : 0;
            }
        };
        viewPager.setAdapter(fragmentPagerAdapter);
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {
 
            }
 
            @Override
            public void onPageSelected(int i) {
                //TODO:
            }
 
            @Override
            public void onPageScrollStateChanged(int i) {
 
            }
        });
 
    }
 
}
複製代碼

在這段代碼中,咱們

首先fragment以及viewpager都實例化;

再將fragment添加到泛型arraylist裏;

最後將帶有fragment的arraylist和adapter綁定。

九、fragment之間傳遞數據的方式?

方法一:

一、在MainFragment中設置一個setData()方法,在方法中設置更改按鈕名稱;

//MainFragment.java文件中

public void setData(String string) {

bt_main.setText(string);

}
複製代碼

二、在MenuFragment中的ListView條目點擊事件中經過標籤獲取到MainFragment,並調用對應的setData()方法,將數據設置進去,從而達到數據傳遞的目的。

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

MainFragment mainFragment =

(MainFragment) getActivity()

.getSupportFragmentManager()

.findFragmentByTag("mainFragment");

mainFragment.setData(mDatas.get(position));

}

});
複製代碼

只需上面區區兩步便可達到數據傳遞的目的。

方法二:

採起接口回調的方式進行數據傳遞。

step1: 在Menuragment中建立一個接口以及接口對應的set方法:

//MenuFragment.java文件中

public interface OnDataTransmissionListener {

public void dataTransmission(String data);

}

public void setOnDataTransmissionListener(OnDataTransmissionListener mListener) {

this.mListener = mListener;

}
複製代碼

step2: 在MenuFragment中的ListView條目點擊事件中進行接口進行接口回調

//MenuFragment.java文件中

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

/**

* 方法二:採起接口回調的方式進行數據傳遞

*/

if (mListener != null) {

mListener.dataTransmission(mDatas.get(position));

}

}

});
複製代碼

step3: 在MainActivity中根據menuFragment獲取到接口的set方法,在這個方法中進行進行數據傳遞,具體以下:

//在MainActivity.java中

menuFragment.setOnDataTransmissionListener(new MenuFragment.OnDataTransmissionListener() {

@Override

public void dataTransmission(String data) {

mainFragment.setData(data); //注:對應的mainFragment此時應該要用final進行修飾

}

});
複製代碼

經過上面的三步也能夠輕鬆作到Fragment數據之間的傳遞。

方法三:

使用三方開源框架:EventBus

那麼問題來了:EventBus是個啥東西???

簡單來講,EventBus是一款針對Android優化的發佈/訂閱(publish/subscribe)事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息。簡化了應用程序內各組件間、組件與後臺線程間的通訊。優勢是開銷小,代碼更優雅,以及將發送者和接收者解耦。好比請求網絡,等網絡返回時經過Handler或Broadcast通知UI,兩個Fragment之間須要經過Listener通訊,這些需求均可以經過EventBus實現。

下面咱們就用EventBus來實現如下Fragment之間的數據傳遞:

step1:引入EventBus

compile 'org.greenrobot:eventbus:3.0.0'
複製代碼

step2:註冊事件接收者

這裏MainFragment是要接收MenuFragment發送來的數據,因此咱們在MainFragment中的onCreateView()方法中進行註冊:

EventBus.getDefault().register(this);
複製代碼

step3:發送事件

注:發送事件以前其實還有一步定義事件類型,這裏咱們傳遞的數據只有一個類型,因此這一步取消了。 MenuFragment發送數據給MainFragment,因此咱們在MenuFragment中將要傳遞的數據進行發送事件操做:

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

EventBus.getDefault().post(mDatas.get(position));

}

});
複製代碼

step4:接收消息並處理

在MainFragment中咱們接收來自MenuFragment傳遞過來的數據,並進行對應的處理(注:EventBus 3.0版本這一步必需要寫註解@Subscribe (與2.4版本有所區別)):

@Subscribe

public void onEvent(String data) {

bt_main.setText(data);

}
複製代碼

經過上面這一步便可完成數據之間的傳遞,須要注意的是在銷燬的時候咱們要註銷事件接收。 step5:註銷事件接收

//MainFragment.java中

@Override

public void onDestroy() {

super.onDestroy();

EventBus.getDefault().unregister(this);

}
複製代碼

以上五步完成了Fragment之間的數據傳遞,看似比上面兩個方法要複雜的多,但當咱們涉及到複雜的Fragment之間數據傳遞(例如Fragment中嵌套多層Fragment)時,就會體會到EventBus的爽快之處~~~這裏不進行贅述了。

十、Activity 怎麼和Service 綁定?

這須要實現service中的onBind()函數以返回service實例給activity

一、建立service類和activity類。

二、在service類中定義一個內部類繼承自Binder()類:

public class MyBinder extends Binder{  

        public Service1 getService(){  

            return Service1.this;  

        }  

    }  
複製代碼

實例化onBind()方法:

private final IBinder binder = new MyyBinder();

@Override

public IBinder onBind(Intent intent){

        Log.i(LOG,"onBind......");

        return binder;

}
複製代碼

三、在activity中完成綁定

Intent intent = new Intent(Activity1.this,Activity2.class);
bindService(intent,conn,Context.BIND_AUTO_CREATE);
// bindService的第二個參數是一個ServiceConnection類型的參數。service和其餘組件之間的鏈接都表示爲一個ServiceConnection,要想將service和其餘組件進行綁定,就須要實現一個新的ServiceConnection。

public ServiceConnection conn= new ServiceConnection() {  
        @Override  
public void onServiceDisconnected(ComponentName name) {  

//當鏈接意外斷開時調用

Log.i(LOG, "onServiceDisconnected>>>>>>>>");  

            myservice = null;  

        }  

          

        @Override  

        public void onServiceConnected(ComponentName name, IBinder service) {  

//當創建鏈接時調用

            Log.i(LOG, "onServiceConnected>>>>>>>>");  

            myservice = ((Service1.MyBinder)service).getService();  

        }  

    }; 
複製代碼
  • bindService的第三個參數是一個flag。

可使用的flag有:

BIND_AUTO_CREATE:綁定完成後就啓動目標service

BIND_DEBUG_UNBIND:這隻在debug時使用,跟unbind有關。

BIND_NOT_FOREGROUND:確保被綁定的service永遠不會有運行於前臺的優先級,由於默認狀況下,綁定一個service會提升它的優先級

BIND_ABOVE_CLIENT:確保客戶端處於前臺時,綁定的service也變爲前臺進程

BIND_ALLOW_OOM_MANAGEMENT:容許系統在低內存等狀態下刪除該service(這是本身對源碼中註釋的理解)

BIND_WAIVE_PRIORITY:綁定service時不改變其優先級

BIND_ADJUST_WITH_ACTIVITY:系統根據service所綁定的activity的重要程度來調整這個service的優先級。

十一、service生命週期?

  1. 被啓動的服務(startService())的生命週期。

若是一個Service被某個Activity 調用Context.startService() 方法啓動,那麼無論是否有Activity使用bindService()綁定或unbindService()解除綁定到該Service,該Service都在後臺運行。若是一個Service被屢次執行startService(),它的onCreate()方法只會調用一次,也就是說該Service只會建立一個實例,而它的onStartCommand()將會被調用屢次(對應調用startService()的次數)。該Service將會一直在後臺運行,直到被調用stopService(),或自身的stopSelf方法。固然若是系統資源不足,系統也可能結束服務。

  1. 被綁定的服務(bindService())的生命週期。

若是一個Service被調用 Context.bindService ()方法綁定啓動,無論調用bindService()調用幾回,onCreate()方法都只會調用一次,而onStartCommand()方法始終不會被調用,這時會調用onBind()方法。當鏈接創建以後,Service將會一直運行,除非調用Context.unbindService() 斷開鏈接或者以前調用bindService() 的 Context 不存在了(如該Activity被finish),系統將會自動中止Service,對應onDestroy()將被調用。

  1. 被啓動又被綁定的服務的生命週期。

若是一個Service又被啓動又被綁定,則該Service將會一直在後臺運行。調用unbindService()將不會中止Service,而必須調用stopService()或Service的stopSelf()方法來中止服務。

  1. 當服務被中止時清除服務。

當一個Service被終止時,Service的onDestroy()方法將會被調用,在這裏應當作一些清除工做,如中止在Service中建立並運行的線程等。

十二、 activity和service的綁定方式以及怎麼在Activity 中啓動本身對應的Service?

一、activity能進行綁定得益於Serviece的接口。爲了支持Service的綁定,實現onBind方法。

二、Service和Activity的鏈接能夠用ServiceConnection來實現。須要實現一個新的ServiceConnection,重現onServiceConnected和OnServiceDisconnected方法,一旦鏈接創建,就能獲得Service實例的引用。

三、執行綁定,調用bindService方法,傳入一個選擇了要綁定的Service的Intent(顯示或隱式)和一個你實現了的ServiceConnection的實例

1三、Service的啓動方式?

採用Context.startService()方法啓動服務,在服務未被建立時,系統會先調用服務的onCreate()方法,接着調用onStart()方法。若是調用startService()方法前服務已經被建立,屢次調用startService()方法並不會致使屢次建立服務,但會致使屢次調用onStart()方法。採用startService()方法啓動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。

採用Context.bindService()方法啓動服務,在服務未被建立時,系統會先調用服務的 onCreate()方法,接着調用onBind()方法。這個時候調用者和服務綁定在一塊兒,調用者退出了,系統就會先調用服務的onUnbind()方 法,接着調用onDestroy()方法。若是調用bindService()方法前服務已經被綁定,屢次調用bindService()方法並不會致使 屢次建立服務及綁定(也就是說onCreate()和onBind()方法並不會被屢次調用)。若是調用者但願與正在綁定的服務解除綁定,能夠調用 unbindService()方法,調用該方法也會致使系統調用服務的onUnbind()-->onDestroy()方法。

1四、談談ContentProvider、ContentResolver、ContentObserver之間的關係?

ContentProvider:

  • 四大組件的內容提供者,主要用於對外提供數據

  • 實現各個應用程序之間的(跨應用)數據共享,好比聯繫人應用中就使用了ContentProvider,你在本身的應用中能夠讀取和修改聯繫人的數據,不過須要得到相應的權限。其實它也只是一箇中間人,真正的數據源是文件或者SQLite等

  • 一個應用實現ContentProvider來提供內容給別的應用來操做,經過ContentResolver來操道別的應用數據,固然在本身的應用中也能夠

ContentResolver:

  • 內容解析者,用於獲取內容提供者提供的數據

  • ContentResolver.notifyChange(uri)發出消息

ContentObserver:

  • 內容監聽器,能夠監聽數據的改變狀態

  • 目的是觀察(捕捉)特定Uri引發的數據庫的變化,繼而作一些相應的處理,它相似於數據庫技術中的觸發器(Trigger),當ContentObserver所觀察的Uri發生變化時,便會觸發它。觸發器分爲表觸發器、行觸發器,相應地ContentObsever也分爲表ContentObserver、行ContentObserver,固然這是與它所監聽的Uri MIME Type有關的

  • ContentResolver.registerContentObserver()監聽消息

1五、廣播的分類?

分爲有序廣播和無序廣播兩類。

  • 無序廣播發送代碼:
public class MainActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
 
    public void click(View v){
        //啓動界面 startActivity
        //發送廣播 sendBroadcast
 
        Intent intent = new Intent();
 
        intent.setAction("com.itheima.cctv.action.NEWS");   
        intent.putExtra("data", "我是一個無須的廣播");
        sendBroadcast(intent);  
    }
}
複製代碼

無序廣播的監聽代碼:

public class CctvReceiver extends BroadcastReceiver {
 
    private static final String TAG = "CctvReceiver";
 
    @Override
    public void onReceive(Context context, Intent intent) {
        String data = intent.getStringExtra("data");
        Log.d(TAG, "data==="+data);
    }
 
}
複製代碼
<receiver android:name="com.itheima.cctv.CctvReceiver">
            <intent-filter >
            <!--這裏監聽的廣播就是上面發送廣播設置的intent.setAction("com.itheima.cctv.action.NEWS");-->
                <action android:name="com.itheima.cctv.action.NEWS"/>
            </intent-filter>
        </receiver>
複製代碼

有序廣播發送:

public class ShengReceiver extends BroadcastReceiver {
@Override
    public void onReceive(Context context, Intent intent) {
        Log.d("vivi", "我是省級部門,我收到的指令是:"+getResultData());
        //getResultData()是用來獲取有序廣播裏面的數值.這裏的信息是:
        //主席講話:每人獎勵10斤土豆

 
        setResultData("主席講話:每人獎勵7斤土豆");//有序廣播的數值,能夠被修改,後面的程序在接受到這個廣播,就會變成,如今咱們改變的值了
 
        //有序廣播傳輸是能夠終止的.可是最終的接受者就算在終止以後,也是能夠接受到數據的
        //abortBroadcast();
    }
}
複製代碼
public class ShiReceiver extends BroadcastReceiver {
 
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("vivi", "我是市級部門,我收到的指令是:"+getResultData());
    //由於上面修改了數據,因此這裏獲取到的數據是:主席講話:每人獎勵7斤土豆
    }
 
}
複製代碼
<!--有序廣播的優先級別使用 android:priority=""來指定,最高是1000,最低是-1000-->
        <receiver android:name="com.itheima.region.ShengReceiver">
            <intent-filter android:priority="1000">
                <action android:name="com.itheima.gov.action.POTATO"/>
            </intent-filter>
        </receiver>
 
        <receiver android:name="com.itheima.region.ShiReceiver">
           <intent-filter android:priority="500">
                <action android:name="com.itheima.gov.action.POTATO"/>
            </intent-filter>
        </receiver>
複製代碼

有序接收:

public class MyReceiver extends BroadcastReceiver {
 
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("vivi", "我是恩恩主席的內線,我收到的指令是:"+getResultData());
    }
 
}
複製代碼

啓動模式:

一、standard:標準化啓動模式

每啓動一個Activity,都會從新建立Activity的新的實例,將其放在棧的頂部。不須要考慮這個實例是否已經存在。

每一次啓動,它的onCreate()、onStart()、onResume()方法都會被依次調用。

二、singleTop:棧頂複用模式

當前棧中已經有該Activity實例,而且該實例位於棧頂時,會去調用onNewIntent()方法。

當前棧中已有該Activity的實例可是該實例不在棧頂時,依然會去建立Activity。

當前棧中不存在該Activity實例時,會去新建立一個該Activity。

應用場景:IM對話框、新聞客戶端推送。

三、singleTask:棧內複用模式

它主要檢測【尋找,經過taskAffinity】整個棧中是否已經存在當前想要啓動的Activity,存在的話直接將該Activity置於棧頂,以前位於該Activity上面的Activity將被銷燬,同時調用onNewIntent()方法,而不存在的話進行建立。

應用場景:應用主界面。

四、singleInstance:

一我的獨享一個任務棧。當該Activity啓動時,系統會建立一個新的任務棧,同時將Activity放到這個新的任務棧當中,有別的應用來啓動該Activity時,因爲棧內複用的特性,不會再去建立相應Activity任務棧,而是這兩個應用獨享一個Activity實例。

例如:應用A中現有兩個Activity E、Activity F,爲standard啓動模式,應用B中有一個Activity G,但其啓動模式是singleInstance。應用A想用應用B任務棧當中的Activity G,儘管在不一樣的應用下,可是應用A仍然會直接複用Activity G。

特性:

一、以SingleInstance模式啓動的Activity具備全局惟一性【全局惟一性即指在整個系統當中只會存在一個這樣的實例】;

二、若是在啓動這樣一個Activity時,【整個系統都是單例的】,已經存在了一個實例;

三、以SingleInstance模式啓動的Activity具備獨佔性。

應用場景:呼叫來電。

問題:onNewIntent()調用時機?

  • singleTop:若是新Activity已經位於任務棧的棧頂,就不會從新建立,並回調 onNewIntent(intent) 方法。
  • singleTask:只要該Activity在一個任務棧中存在,都不會從新建立,並回調 onNewIntent(intent) 方法。

網絡協議:

協議:【協議指計算機通訊網絡中兩臺計算機之間進行通訊所必須共同遵照的規定或規則】

HTTP協議 基本概念:【超文本傳輸協議】容許將HTML(超文本標記語言)文檔從Web服務器傳送到客戶端的瀏覽器。HTTP協議是
基於TCP/IP通訊協議來傳輸數據的,能夠從服務器端獲取圖片等數據資源。 URI:【uniform resource identifier】統一的資源標識符,用來惟一的標識一個資源。強調資源!!! 組成部分: 1)訪問資源的命名機制;file 2)存放資源的主機名; 3)資源自身的名稱,由路徑表示,着重於強調資源。 例:file://a:1234/b/c/d.txt 表示資源目標在a主機下的1234端口的b目錄下的c目錄下的d.txt文件。 URL:【uniform resource Location】統一資源定位器,是一種具體的URI。即URL能夠用來標識一個資源,並且還指明瞭如何定位這個資源。強調路徑!!! 組成部分: 1)協議; 2)存有該資源的主機IP地址; 3)主機資源的具體地址。 HTTP協議特色: 1)簡單快速; 2)無鏈接;【限制每次連接只處理一個請求,服務器處理完客戶的請求以後會收到客戶端的應答,再斷開連接,節省了重複的時間】; 3)無狀態:【沒有記憶能力,】 HTTP協議的request/response請求頭原理剖析: request有可能通過代理服務器到達web服務器 代理服務器最主要的做用:提升訪問速度【大部分代理服務器都具備緩存功能,當你再次訪問前一個網絡請求時,就能夠直接從代理服務器中獲取,而不須要請求咱們的web服務器】。

HTTP協議容易混淆知識點:

(1)http1.0與http1.1的具體區別: http處於計算機網絡的應用層。 1)緩存處理 2)帶寬優化及網絡鏈接的使用 3)Host頭使用:1.1上請求操做和響應操做都支持Host頭,並且在請求消息中若是沒有Host頭的話會報告一個400錯誤。 4)長鏈接:在一個TCP鏈接上,能夠傳送多個HTTP請求和響應,而不是發送一個HTTP請求就斷開一個鏈接,再發送一個HTTP請求再創建一個鏈接。 存在的問題: 1)傳輸數據時,每次都須要從新建立鏈接,增長了大量的延遲時間; 2)傳輸數據時,全部傳輸的內容都是明文,客戶端和服務器端都沒法驗證對方的身份; 3)使用時,header裏攜帶的內容過大,增長了傳輸成本。 (2)get / post方法的區別: 1)提交的數據:get提交的數據通常會放在咱們的URL以後,用「?」來分割;而post提交數據都會放在咱們entity- body【消息主體】當中。 2)提交的數據大小是否有限制:get提交的數據是有限制的,由於url是有限制的,不能無限制的輸入一個url地址;而post方法提交的是body,所以沒有限制。 3)取得變量的值:get方法經過Request.QueryString()來取得變量的值,而post方法經過Request.Form來取得變量的值。 4)安全問題:get提交數據必定會帶來安全問題 (3)Cookie和Session的區別: 1)cookie【用戶身份的標識】:客戶端的解決方案。是由服務器發給客戶端的特殊信息,而這些信息以文本文件的方式存放在客戶端,而後客戶端每次向服務器發送請求的時候都會帶上這些特殊的信息。存放在響應頭裏面。 客戶端 向服務端發送一個HTTP Request請求; 服務端給客戶端一個HTTP Response ,而且把它的cookies設置給咱們的客戶端; 客戶端將HTTP Request和cookies打包給咱們的服務端; 服務端會根據客戶端給咱們的cookies來進行指定的判斷,返回HTTP Response給咱們的客戶端。 此方法彌補了咱們HTTP協議無狀態的不足。以前當上述請求響應操做完成後,服務端和客戶端就斷開鏈接,服務就沒法從鏈接上跟蹤咱們所想要的客戶端。 2)session:另外一種記錄客戶狀態的限制,cookie保存在客戶端瀏覽器中,而session保存在服務器上。客戶端瀏覽器訪問服務器時,服務器把客戶端信息以某種形式記錄在服務器上。 建立session; 在建立session同時,服務器會爲該session生成惟一的session id; 在session被建立以後,就能夠調用session相關的方法往session中增長內容; 當客戶端再次發送請求的時候,會將這個session id帶上,服務器接收到請求以後就會依據session id找到相應的session。 3)區別: 存放的位置不一樣; 存取的方式不一樣【cookie保存的是Ascll碼字符串,而session中可以保存任何類型的數據】; 安全性上的不一樣【cookie存放在客戶端瀏覽器中,對咱們客戶端可見,客戶端的一些程序就有可能去修改咱們cookie的內容,而session則否則,它存儲在服務端上,對客戶端是透明的,不存在敏感信息泄露的風險】; 有效期上的不一樣【通常咱們會設置cookie過時時間, session依賴 id,若id設置爲-1,當關掉瀏覽器session就會失效】; 對服務器的形成的壓力不一樣【cookie保存在客戶端不佔用客戶資源,session保存在服務端,每個用戶都會產生一個session。在併發不少用戶時cookie是一個很好的選擇】。 HTTPS協議: 基本概念:對工做在以加密鏈接(SSL / TLS)上的常規HTTP協議。經過在TCP和HTTP之間加入TLS【Transport LayerSecurity】來加密。 SSL / TLS協議:安全傳輸協議,TLS是SSL的升級版,也是現階段所使用的協議; HTTPS傳輸速度: 1)通訊慢; 2)SSL必須進行加密處理。 TLS / SSL握手: 1)密碼學原理 對稱加密:加密數據所用的密鑰和解密數據所用的密鑰相同。 非對稱加密:分私有密鑰和公有密鑰。 2)數字證書:互聯網通信中標誌通信各方身份信息的一串數字。 3)握手過程

Handler【Android SDK提供給開發者方便進行異步消息處理的類】:

AsyncTask、retrofit都對Handler進行了封裝。 (1)Handler四大組件 1)Message Message是在線程之間傳遞的消息,它能夠在內部攜帶少許的信息,用於在不一樣線程之間交換數據。 例:Message的what字段、arg1字段、arg2字段來攜帶整型數據,obj字段攜帶一個Object對象。 2)Handler 處理者,它主要用來發送和處理消息。發送消息通常是使用Handler的sendMessage()方法,消息通過處理後,最終傳遞到Handler的handlerMessage()方法中 3)MessageQueue 消息隊列,它主要用來存放全部經過Handler發送的消息,這部分消息會一直存在於消息隊列中,等待被處理。 注意:每一個線程中只會有一個MessageQueue對象。 4)Looper 是每一個線程中MessageQueue的管家,調用Looper的loop()方法後,就會進入到一個無限循環當中,每當發現MessageQueue中存在一條消息,就會將其取出傳遞到Handler的handleMessage()方法當中。 注意:每一個線程中只會有一個Looper對象。 異步消息處理流程: 1)在主線程當中建立一個Handler對象; 2)重寫handleMessage()方法; 3)當子線程須要進行UI操做時,建立一個Message對象,並經過Handler將消息發送出去; 4)消息添加到MessageQueue的隊列中等待被處理; 5)Looper在MessageQueue中取出待處理消息,發回Handler的handleMessage()方法中。 【因爲Handler是在主線程中建立的,所以咱們的handleMessage()方法中的代碼也會在主線程中執行,避免了異常的產生】

Handler消息機制:

  • 做用: 跨線程通訊。當子線程中進行耗時操做後須要更新UI時,經過Handler將有關UI的操做切換到主線程中執行。
  • 四要素:

Message(消息):須要被傳遞的消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,最終由Handler處理。

MessageQueue(消息隊列):用來存放Handler發送過來的消息,內部經過單鏈表的數據結構來維護消息列表,等待Looper的抽取。

Handler(處理者):負責Message的發送及處理。經過 Handler.sendMessage() 向消息池發送各類消息事件;經過 Handler.handleMessage() 處理相應的消息事件。

Looper(消息泵):經過Looper.loop()不斷地從MessageQueue中抽取Message,按分發機制將消息分發給目標處理者。 具體流程如圖

  • Handler.sendMessage()發送消息時,會經過MessageQueue.enqueueMessage()向MessageQueue中添加一條消息;
  • 經過Looper.loop()開啓循環後,不斷輪詢調用MessageQueue.next();
  • 調用目標Handler.dispatchMessage()去傳遞消息,目標Handler收到消息後調用Handler.handlerMessage()處理消息。

最後送福利了,如今關注我而且加入羣聊能夠獲取包含源碼解析,自定義View,動畫實現,架構分享等。 內容難度適中,篇幅精煉,天天只需花上十幾分鍾閱讀便可。 你們能夠跟我一塊兒探討,歡迎加羣探討,有flutter—性能優化—移動架構—資深UI工程師 —NDK相關專業人員和視頻教學資料,還有更多面試題等你來拿~ 羣號:661841852

QQ截圖20190510143109.jpg
點擊連接加入羣聊【Android開發行業交流】: jq.qq.com/?_wv=1027&a…
相關文章
相關標籤/搜索