Activity【活动】:用于表现功能。java
Service【服务】:后台运行服务,不提供界面呈现。android
BroadcastReceiver【广播接收器】:用来接收广播。web
Content Provider【内容提供商】:支持在多个应用中存储和读取数据,至关于数据库。面试
Service的生命周期:首先Service有两种启动方式,而在这两种启动方式下,它的生命周期不一样。数据库
经过startService()方法启动的服务浏览器
初始化结束后系统会调用 void onStart(Intent intent) 方法,用于处理传递给startService()的Intent对象。如音乐服务会打开Intent 来探明将要播放哪首音乐,并开始播放。注意:屡次调用startService()方法会屡次触发onStart()方法。缓存
经过bindService ()方法启动的服务安全
初始化结束后系统会调用 IBinder onBind(Intent intent) 方法,用来绑定传递给bindService 的Intent 的对象。注意:屡次调用bindService()时,若是该服务已启动则不会再触发此方法。性能优化
当咱们的Activity上弹出Dialog对话框时,程序的生命周期依然是onCreate() ---> onStart() ---> onResume(),在弹出Dialog的时候并无onPause()和onStop()方法。而在此时咱们按下Home键,才会继续执行onPause()和onStop()方法。这说明对话框并无使Activity进入后台,而是在点击了Home键后Activity才进入后台工做。bash
缘由就是,其实Dialog是Activity的一个组件,此时Activity并非不可见,而是被Dialog组件覆盖了其余的组件,此时咱们没法对其余组件进行操做而已。
首先定义两个Activity,分别为A和B。
当咱们在A中激活B时,A调用onPause()方法,此时B出如今屏幕时,B调用onCreate()、onStart()、onResume()。
这个时候B【B不是一个透明的窗体或对话框的形式】已经覆盖了A的窗体,A会调用onStop()方法。
首先定义两个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的生命周期与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是否被切换到后台或前台,因此在这里也看成生命周期)
NF: setUserVisibleHint(false)【用户不可见】 > onAttach > onCreate > setUserVisibleHint(true)【用户可见】 > onCreateView > onViewCreated > onActivityCreated > onStart > onResume
OF跟NF相邻: setUserVisibleHint(false) > onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume
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中间:不调用任何生命周期方法
相互切换时只会调用setUserVisibleHint
Fragment进入了运行状态:
Fragment在进入运行状态时,如下四个生命周期会随它所属的Activity一块儿被调用:
onPause() ---> onStop() ---> onStart() ---> onResume()
关于Fragment的onActivityResult方法:
使用Fragment的startActivity方法时,FragmentActivity的onActivityResult方法会回调相应的Fragment的onActivityResult方法,因此在重写FragmentActivity的onActivityResult方法时,注意调用super.onActivityResult。
将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绑定。
方法一:
一、在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的爽快之处~~~这里不进行赘述了。
这须要实现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();
}
};
复制代码
可使用的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被某个Activity 调用Context.startService() 方法启动,那么无论是否有Activity使用bindService()绑定或unbindService()解除绑定到该Service,该Service都在后台运行。若是一个Service被屡次执行startService(),它的onCreate()方法只会调用一次,也就是说该Service只会建立一个实例,而它的onStartCommand()将会被调用屡次(对应调用startService()的次数)。该Service将会一直在后台运行,直到被调用stopService(),或自身的stopSelf方法。固然若是系统资源不足,系统也可能结束服务。
若是一个Service被调用 Context.bindService ()方法绑定启动,无论调用bindService()调用几回,onCreate()方法都只会调用一次,而onStartCommand()方法始终不会被调用,这时会调用onBind()方法。当链接创建以后,Service将会一直运行,除非调用Context.unbindService() 断开链接或者以前调用bindService() 的 Context 不存在了(如该Activity被finish),系统将会自动中止Service,对应onDestroy()将被调用。
若是一个Service又被启动又被绑定,则该Service将会一直在后台运行。调用unbindService()将不会中止Service,而必须调用stopService()或Service的stopSelf()方法来中止服务。
当一个Service被终止时,Service的onDestroy()方法将会被调用,在这里应当作一些清除工做,如中止在Service中建立并运行的线程等。
一、activity能进行绑定得益于Serviece的接口。为了支持Service的绑定,实现onBind方法。
二、Service和Activity的链接能够用ServiceConnection来实现。须要实现一个新的ServiceConnection,重现onServiceConnected和OnServiceDisconnected方法,一旦链接创建,就能获得Service实例的引用。
三、执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显示或隐式)和一个你实现了的ServiceConnection的实例
采用Context.startService()方法启动服务,在服务未被建立时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。若是调用startService()方法前服务已经被建立,屡次调用startService()方法并不会致使屡次建立服务,但会致使屡次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
采用Context.bindService()方法启动服务,在服务未被建立时,系统会先调用服务的 onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一块儿,调用者退出了,系统就会先调用服务的onUnbind()方 法,接着调用onDestroy()方法。若是调用bindService()方法前服务已经被绑定,屡次调用bindService()方法并不会致使 屡次建立服务及绑定(也就是说onCreate()和onBind()方法并不会被屡次调用)。若是调用者但愿与正在绑定的服务解除绑定,能够调用 unbindService()方法,调用该方法也会致使系统调用服务的onUnbind()-->onDestroy()方法。
四大组件的内容提供者,主要用于对外提供数据
实现各个应用程序之间的(跨应用)数据共享,好比联系人应用中就使用了ContentProvider,你在本身的应用中能够读取和修改联系人的数据,不过须要得到相应的权限。其实它也只是一个中间人,真正的数据源是文件或者SQLite等
一个应用实现ContentProvider来提供内容给别的应用来操做,经过ContentResolver来操道别的应用数据,固然在本身的应用中也能够
内容解析者,用于获取内容提供者提供的数据
ContentResolver.notifyChange(uri)发出消息
内容监听器,能够监听数据的改变状态
目的是观察(捕捉)特定Uri引发的数据库的变化,继而作一些相应的处理,它相似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObsever也分为表ContentObserver、行ContentObserver,固然这是与它所监听的Uri MIME Type有关的
ContentResolver.registerContentObserver()监听消息
分为有序广播和无序广播两类。
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()调用时机?
协议:【协议指计算机通讯网络中两台计算机之间进行通讯所必须共同遵照的规定或规则】
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服务器】。
(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)握手过程
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消息机制:
Message(消息):须要被传递的消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,最终由Handler处理。
MessageQueue(消息队列):用来存放Handler发送过来的消息,内部经过单链表的数据结构来维护消息列表,等待Looper的抽取。
Handler(处理者):负责Message的发送及处理。经过 Handler.sendMessage() 向消息池发送各类消息事件;经过 Handler.handleMessage() 处理相应的消息事件。
Looper(消息泵):经过Looper.loop()不断地从MessageQueue中抽取Message,按分发机制将消息分发给目标处理者。 具体流程如图
最后送福利了,如今关注我而且加入群聊能够获取包含源码解析,自定义View,动画实现,架构分享等。 内容难度适中,篇幅精炼,天天只需花上十几分钟阅读便可。 你们能够跟我一块儿探讨,欢迎加群探讨,有flutter—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿~ 群号:661841852