Android四大組件:
activity:
-
activity的生命周期:activity是context的子類,同時實(shí)現(xiàn)了window.callback 和 keyevent.callback.可以處理與窗體用戶交互的事件云矫。activity從創(chuàng)建到銷毀有多種狀態(tài)舵匾,在這些狀態(tài)轉(zhuǎn)換的時候伴隨有回調(diào)方法:onCreate(創(chuàng)建 )轻黑,onStart(可見)氯迂,onResume(可交互),onPause(不可交互)冯事,onStop(不可見)宿接,onDestory(銷毀)赘淮,onRestart(重新可見).
- activity在一創(chuàng)建的時候會執(zhí)行onCreate(),onStart()睦霎,onResume()梢卸,在A界面上啟動B界面的之后,A界面會執(zhí)行onPause(),onStop()方法副女,如果B界面是一個diaLog蛤高,A界面處于可見但不可交互的狀態(tài),會執(zhí)行onStop()方法,由B界面返回A界面會執(zhí)行onReStart()襟齿,onstart(),onResume()方法姻锁,退出A界面會執(zhí)行onPause()枕赵,onStop()猜欺,onDestory()方法。
-
activity的幾種啟動模式:包括:標(biāo)準(zhǔn)模式(standard)拷窜,singleTop开皿,singleTask,singleInstance篮昧。
- 標(biāo)準(zhǔn)啟動模式是說:默認(rèn)的啟動模式赋荆,可以不用配置,會隨著每個activity的開啟懊昨,每次都會創(chuàng)建一個實(shí)例對象窄潭,可以有多個實(shí)例對象,也可以多個相同的activity疊加酵颁。在點(diǎn)擊back退出時會依照棧順序依次退出嫉你。
- singleTop是說:可以有多個實(shí)例對象,但不可以多個相同activity疊加躏惋,如果activity在棧頂幽污,啟動相同的activity,不會創(chuàng)建新的實(shí)例簿姨,而會調(diào)用它的onNewIntent方法距误。
- singleTask是說:只有一個實(shí)例對象,在同一個應(yīng)用程序中啟動它時扁位,若該activity不存在准潭,就會在當(dāng)前的任務(wù)棧中創(chuàng)建一個新的實(shí)例,若存在域仇,則會把任務(wù)棧中所有在其之上的activity全部destory之后再調(diào)用其onNewIntent方法刑然。而如果說在其他的應(yīng)用程序中啟動它,則會新建一個task殉簸,并在該task中啟動這個activity闰集,singleTask允許別的activity與其在統(tǒng)一個task中共存,也就是說般卑,如果我在這個singleTask的實(shí)例中在啟動新的activity武鲁,這個新的activity還是會存在這一個singleTask的實(shí)例的任務(wù)棧中。
- singleInstance是說:只有一個實(shí)例蝠检,并且這個實(shí)例只運(yùn)行在一個task中沐鼠,在這個task中只有這一個實(shí)例,不允許在有其他activity存在理卑。
-
如何保存和恢復(fù)Activity的狀態(tài)數(shù)據(jù):
- activity的狀態(tài)通常情況下系統(tǒng)會自動保存蛔翅,一般來說,在調(diào)用onPause()和onStop()方法之后倾芝,activity的實(shí)例仍然保存在內(nèi)存中憔涉,activity的所有信息和狀態(tài)數(shù)據(jù)都不會丟失订框,當(dāng)activity重新回到前臺之后,所有的改變都會保留兜叨,
- 但是當(dāng)系統(tǒng)內(nèi)存不足時穿扳,調(diào)用onPause()和onStop()方法之后的activity可能會被系統(tǒng)銷毀,此時內(nèi)存中就沒有了這個activity的實(shí)例對象了国旷,如果這個activity重新回到前臺矛物,所有的改變都會消失,為了避免該情況的發(fā)生跪但,可以覆寫onsaveInstanceState()方法履羞。onsaveInstanceState()方法接收一個bundle類型的參數(shù),可以將狀態(tài)數(shù)據(jù)存儲在bundle中屡久,這樣即使activity銷毀忆首,用戶在次啟動activity,在調(diào)用它的onCreate(),上述的bundle對象會作為實(shí)參來傳遞給onCreate()方法涂身,然后可以從bundle中獲取到保存的數(shù)據(jù)雄卷,將activity恢復(fù)到銷毀前的樣子。需要注意的是調(diào)用onsaveInstanceState()方法蛤售,要在方法onPause()和onStop()調(diào)用之前丁鹉。
-
兩個activity之間跳轉(zhuǎn)必然會執(zhí)行那些方法;
- 兩個activity悴能,從A跳轉(zhuǎn)至B揣钦,當(dāng)B是一個對話框時或者透明窗體時,A會調(diào)用onPause()方法漠酿,B會調(diào)用onCreate()冯凹,onStart(),onResume(),當(dāng)B覆蓋A時炒嘲,A會調(diào)用onStop()方法宇姚。
-
Android中activity,context夫凸,application之間有什么區(qū)別浑劳;
- 相同點(diǎn):context是描述一個應(yīng)用程序環(huán)境的信息,即上下文的意思夭拌,該類是一個抽象類(abstract class)魔熏,Android有提供該抽象類的具體實(shí)現(xiàn)類(contextlml)衷咽,activity和application都是context的子類。
- 不同點(diǎn): 維護(hù)的生命周期不同蒜绽。context維護(hù)的是當(dāng)前activity的生命周期镶骗,而application維護(hù)的是整個項(xiàng)目的生命周期。
- 在使用context的時候躲雅,需要防止內(nèi)存泄漏鼎姊,需要注意幾點(diǎn):
- 不要讓生命周期長的對象引用activity context,即保證引用activity的對象要與activity本身的生命周期相同吏夯;
- 對于生命周期長的使用application context此蜈;
- 避免使用非靜態(tài)內(nèi)部類即横,盡量使用靜態(tài)類噪生,避免生命周期的問題,注意內(nèi)部類對外部對象引用時導(dǎo)致的生命周期的變化东囚。
-
如何退出activity跺嗽?如何安全的退出已調(diào)用多個activity的application;
通常退出一個activity只需要按返回鍵页藻,代碼中直接調(diào)用finish()方法就行桨嫁,
用數(shù)組記錄住打開的每一個activity,在需要退出的時候份帐,遍歷璃吧,調(diào)用finish()方法關(guān)閉每一個activity即可。
發(fā)送特定的廣播
在需要結(jié)束應(yīng)用時废境,發(fā)送一個特定的廣播畜挨,每個Activity 收到廣播后,關(guān)閉即可噩凹。
//給某個activity 注冊接受接受廣播的意圖
registerReceiver(receiver, filter)
//如果過接受到的是關(guān)閉activity 的廣播就調(diào)用finish()方法把當(dāng)前的activity finish()掉遞歸退出巴元。在打開新的Activity時使用startActivityForResult,然后自己添加標(biāo)志,在onActivityResult()中處理驮宴,遞歸關(guān)閉逮刨。
-
兩個activity之間如何傳遞數(shù)據(jù);
- 傳遞的方式有:intent堵泽,廣播接收者修己,contentProvider,static靜態(tài)數(shù)據(jù)(public static 成員變量)迎罗,file文件存儲睬愤,sharedPreferences,sqlite數(shù)據(jù)庫.
service:
-
service是在main方法中執(zhí)行佳谦,service中能否執(zhí)行耗時操作戴涝;
- 默認(rèn)情況下,如果沒有顯示的是指service所運(yùn)行的進(jìn)程,service和activity是運(yùn)行在當(dāng)前APP所在進(jìn)程的主線程(main thread)中啥刻,service中不能進(jìn)行耗時操作(網(wǎng)絡(luò)操作奸鸯,拷貝數(shù)據(jù)庫,大文件)可帽,
- 特殊情況下娄涩,可以在清單文件中進(jìn)行配置service所執(zhí)行的進(jìn)程,讓service在其他進(jìn)程中執(zhí)行映跟。
-
activity怎樣和service綁定蓄拣,怎樣在activity中啟動對應(yīng)的service;
- activity通過bindService(intent service努隙,ServiceConnection conn球恤,int flags)跟service進(jìn)行綁定,當(dāng)綁定成功之后荸镊,service會將代理對象通過回調(diào)的方式傳遞給conn,這樣就可以拿到Service提供的代理對象了咽斧。一般情況下, 如果想獲取Service的服務(wù)對象那么就需要通過bindService()躬存,比如张惹,音樂播放器,第三方支付岭洲。
- activity還可以通過startService()宛逗,通常僅需要開啟一個后臺任務(wù)的時候用startService()。
-
service的生命周期盾剩;
- service有綁定模式和非綁定模式雷激,以及兩種的混合模式,不同的模式生命周期不同彪腔;
- 非綁定模式:當(dāng)?shù)谝淮握{(diào)用startService的時候執(zhí)行onCreate()侥锦,onStartCommand(),當(dāng)service關(guān)閉的時候執(zhí)行onDestory()德挣;
- 綁定模式:當(dāng)?shù)谝淮握{(diào)用bindService()的時候恭垦,執(zhí)行onCreate(),onBind()格嗅,當(dāng)解除綁定的時候執(zhí)行onUnbind()番挺,onDestory()。
- 還需要注意的是service實(shí)例只會有一個屯掖,也就是說如果當(dāng)前要啟動的service已經(jīng)存在了玄柏,那就不需用在啟動service了,也就不會在調(diào)用onCreate()方法了贴铜。
- 一個service被多個客戶所綁定粪摘,只有所有的綁定對象都執(zhí)行了onBind()方法后該service才會銷毀瀑晒,但是如果有一個客戶執(zhí)行了onStart()方法,那么這個時候即使所有的service都執(zhí)行了onBind()方法徘意,service也不會銷毀苔悦。
- service有綁定模式和非綁定模式雷激,以及兩種的混合模式,不同的模式生命周期不同彪腔;
-
什么是IntentService?有什么優(yōu)點(diǎn)?
- intentService是service的子類椎咧,比起普通的service有了新的功能玖详。普通的service存在兩個問題:service不會啟動一條單獨(dú)的線程,service與他所在的應(yīng)用位于同一個進(jìn)程中勤讽;不能在service中直接處理耗時操作蟋座。
- intentService的特征:會創(chuàng)建獨(dú)立的worker線程來處理所有的intent請求;會創(chuàng)建獨(dú)立worker線程來處理onHandlerIntent()方法實(shí)現(xiàn)的代碼脚牍,無需處理多線程問題向臀;所有請求處理完成后,IntentService會自動停止莫矗,無需調(diào)用stopSelf()方法來停止Service飒硅;為service的onBind()方法提供默認(rèn)的實(shí)現(xiàn),返回null作谚;為service的onStartCommard()方法提供默認(rèn)實(shí)現(xiàn),將請求intent添加到請求隊(duì)列中庵芭。
-
activity妹懒,service,intent之間的關(guān)系双吆?
- activity負(fù)責(zé)用戶界面的顯示和交互眨唬,Service負(fù)責(zé)后臺任務(wù)的處理,activity和service之間通過intent傳遞數(shù)據(jù)好乐,activity和service都是context的子類contextWrapper的子類匾竿。
-
service中可以談吐司嗎?
- 可以的蔚万,但是得有個條件就是得有一個context上下文岭妖,由于service是context的子類,因此談吐司是可以的反璃。比如在service中完成任務(wù)的下載之后彈一個土司來提醒一下用戶是完全可以的昵慌。
-
service有哪些啟動方法。有什么區(qū)別淮蜈,怎樣停用service斋攀?
- 通過startService()方法,service啟動之后會調(diào)用onCreate(),onStart()方法處于運(yùn)行狀態(tài),stopService的時候調(diào)用onDestory()方法停止服務(wù)梧田,而如果調(diào)用者自己直接退出而沒有調(diào)用stopService的方法時淳蔼,service會一直運(yùn)行在后臺侧蘸。
- 通過bindService()方法,service啟動后回調(diào)用onCreate()方法鹉梨,然后調(diào)用onBind()方法闺魏,這個時候調(diào)用者會和service綁定在一起,如果調(diào)用者退出了俯画,service就會調(diào)用onUnbind()析桥,onDestory()方法退出。調(diào)用者也可以調(diào)用unbindService()來停止服務(wù)艰垂。
- 需要注意的原則:service的onCreate()方法只會被調(diào)用一次泡仗,就是無論多少次的startService或者bindService,service只會被創(chuàng)建一次猜憎。
- 如果service在運(yùn)行期間調(diào)用了bindService娩怎,這時候在調(diào)用stopService,service是不會調(diào)用onDestory方法的胰柑,service就停止不了了截亦。只有在調(diào)用了UnbindService之后,service才會被銷毀柬讨。
- 如果一個service通過startService被start之后崩瓤,多次調(diào)用startService方法的話,這個時候會多次調(diào)用onStart方法踩官,多次的調(diào)用stopService方法却桶,但是onDestory方法只會被調(diào)用一次。
- 如果一個service通過bindService被start之后蔗牡,多次調(diào)用bindService方法的話颖系,service之后調(diào)用一個onBind方法,多次調(diào)用unbindService方法會拋異常辩越。
broadcast receiver:
-
什么是broadcast receiver嘁扼,生命周期是什么?
- broadCast receiver 廣播接收者黔攒,分為有序和無序趁啸,內(nèi)部實(shí)現(xiàn)機(jī)制是通過Android系統(tǒng)的binder機(jī)制實(shí)現(xiàn)通信的。
- 無序廣播:完全異步亏钩,邏輯上是可以被任何的廣播接收者接收到莲绰,效率較高,但是無法一個接受者不能將處理結(jié)果傳遞給下一個接受者姑丑,并無法終止廣播intent的傳播蛤签。
- 有序廣播:按照被接受者的優(yōu)先級順序,在被接受者中依次傳播栅哀。
-
在mainfast和代碼中如何注冊和使用broadcast receiver震肮。
-
靜態(tài)注冊:在mainfast.xml文件中注冊称龙。靜態(tài)注冊的廣播,只要應(yīng)用一直在系統(tǒng)中運(yùn)行就會一直接收到廣播信息戳晌。
<receiver android:name=".BroadcastReceiver1" > <intent-filter> <action android:name="android.intent.action.CALL" > </action> </intent-filter> </receiver>
-
動態(tài)注冊:在代碼中注冊鲫尊。動態(tài)注冊的的廣播,當(dāng)注冊的activity或者service銷毀了沦偎,就接收不到廣播了疫向。
receiver = new BroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(CALL_ACTION); context.registerReceiver(receiver, intentFilter);
-
-
broadcastReceiver的生命周期;
- 廣播接受者的生命周期很短暫豪嚎,在接收到廣播的時候創(chuàng)建搔驼,onReceive()方法結(jié)束之后銷毀。
- 廣播接收者中不要做一些耗時操作侈询,否則會引起ANR舌涨,耗時較長的最好放在service中進(jìn)行。
- 最好不要再廣播接收者中創(chuàng)建子線程做耗時操作扔字,因?yàn)閺V播接收者被銷毀之后囊嘉,進(jìn)程就變成了空進(jìn)程,很容易被系統(tǒng)清理掉革为。
contentProvider :
-
contentProvider是如何實(shí)現(xiàn)數(shù)據(jù)共享的扭粱?
-
contentProvider是應(yīng)用程序見間共享數(shù)據(jù)的接口,使用的話需要先自定義一個類繼承ContentProvider篷角,然后覆寫實(shí)現(xiàn)query焊刹,insert,update恳蹲,delete四個方法。好需要在清單文件中進(jìn)行注冊俩滥。
public class PersonContentProvider extends ContentProvider{ public boolean onCreate(){ } query(Uri, String[], String, String[], String); insert(Uri, ContentValues); update(Uri, ContentValues, String, String[]); delete(Uri, String, String[]); }
-
-
Android中的數(shù)據(jù)存儲的方式嘉蕾?
- file文件,sharedPreference霜旧,conteneProvider,SQLite數(shù)據(jù)庫错忱,網(wǎng)絡(luò)存儲。
-
說出contentProvider挂据,contentResolver以清, contentObserver之間的關(guān)系?
- contentProvider崎逃,內(nèi)容提供者掷倔,用于對外提供數(shù)據(jù);
- contentResolver个绍,內(nèi)容解析者勒葱,用于獲取內(nèi)容提供者提供的數(shù)據(jù)浪汪;contentResolver.notifyChange(uri)發(fā)出消息。
- contentObserver凛虽,內(nèi)容觀察者死遭,用于監(jiān)聽內(nèi)容數(shù)據(jù)的改變主狀態(tài)。contentResolver.registercontentObserver()監(jiān)聽消息凯旋。
-
contentObserver內(nèi)容觀察者的作用及特點(diǎn)呀潭?
- contentObserver目的是觀察特定的uri引起的數(shù)據(jù)庫的變化。繼而做一些相應(yīng)的處理至非。
- 觀察特定的uri的步驟:
- 創(chuàng)建特定的contentObserver派生類钠署,必須重載父類的構(gòu)造方法,必須重載onChange()方法去處理回調(diào)后的功能實(shí)現(xiàn)睡蟋。
- 利用context.getContentResolover()獲取contentResolover對象踏幻,接著調(diào)用registerContentObserver()方法去注冊內(nèi)容觀察者;
- 在不需要時戳杀,需要手動的調(diào)用unregisterContentObserver()去取消注冊该面。
intent:
-
intent傳遞數(shù)據(jù)可以傳遞那些類型數(shù)據(jù)?
- 八大基本數(shù)據(jù)類型和String以及數(shù)組形式都可以,還可以傳遞實(shí)現(xiàn)了Serializable和Parcelable接口的對象信卡。
-
描述intent和intentFliter是什么隔缀?
- Android中通過intent對象來表示一條消息,通過intent可以實(shí)現(xiàn)各種系統(tǒng)組件的調(diào)用和激活傍菇。
- intentFliter可以理解為一個郵局或者一個信箋的分揀系統(tǒng)猾瘸。
listview:
- listview的優(yōu)化方式;
復(fù)用convertView,優(yōu)化加載布局丢习,如果沒有緩存就加載布局牵触,如果有緩存就直接使用conventView對象,這樣在滑動listview的時候就不用每次都去調(diào)用gitView()方法去加載布局了咐低。
-
使用自定義靜態(tài)類viewHolder揽思,減少fingviewById的次數(shù),convertView為空的時候见擦,viewHolder會將空間里的實(shí)例存放在viewHolder中钉汗,然后用setTag()的方法將viewHolder對象存放在view中。conventView不為空的時候鲤屡,用getTag()的方法獲取viewHolder對象损痰。
public View getView(int position, View convertView, ViewGroup parent) { Log.d("MyAdapter", "Position:" + position + "---" + String.valueOf(System.currentTimeMillis())); ViewHolder holder; if (convertView == null) { final LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.list_item_icon_text, null); holder = new ViewHolder(); holder.icon = (ImageView) convertView.findViewById(R.id.icon); holder.text = (TextView) convertView.findViewById(R.id.text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.icon.setImageResource(R.drawable.icon); holder.text.setText(mData[position]); return convertView; } static class ViewHolder { ImageView icon; TextView text; }
-
異步加載數(shù)據(jù),分頁加載數(shù)據(jù)酒来;
-
listview的分頁加載卢未, 設(shè)置listview的滾動監(jiān)聽器,setOnScrollListener(new OnScrollListener { ... })役首;該監(jiān)聽器有兩個方法尝丐,onScrollStateChanged()--滾動狀態(tài)發(fā)生改變的時候显拜,onScroll()0--listview被滾動時調(diào)用的方法。在滾動狀態(tài)發(fā)生改變的時候爹袁,有三種狀態(tài):
- 手指按下移動的狀態(tài):SCROLL_STATE_TOUCH_SCROLL :觸摸滑動远荠。
- 慣性滾動狀態(tài):SCROLL_STATE_FLING : (滑翔 )
- 靜止?fàn)顟B(tài):SCROLL_STATE_IDLE : 靜止。
對不同的狀態(tài)進(jìn)行處理:分批加載數(shù)據(jù)失息,只關(guān)心靜態(tài)狀態(tài):關(guān)心最后一個可見的條目譬淳,如果最后一個可見條目就是適配器里的最后一個,此時就可加載更多的數(shù)據(jù)盹兢,在每次加載的時候邻梆, 計(jì)算出滾動的數(shù)量,當(dāng)滾動的數(shù)量大于等于總數(shù)量的時候绎秒,可以提示用戶無更多的數(shù)據(jù)浦妄。
-
-
listview數(shù)據(jù)集改變之后,如何更新listview见芹?
- 使用listview的adapter的notifyDataSetChange()方法剂娄,該方法會使listview重新繪制。
-
listview能否實(shí)現(xiàn)多種類型的條目玄呛?
- 可以阅懦,listview顯示的每個條目都是通過baseAdapter的gitView(int position,View convertView,ViewGroup parent)來展示的,理論上可以讓每個條目都是不同類型的view徘铝。
- 另外耳胎,adapter還提供了getViewTypeCount()和getItemViewType(int position)兩個方法,在getView方法中可以根據(jù)不同的viewtype加載不同的布局文件惕它。
-
listview如何跳轉(zhuǎn)到指定位置怕午?
- 可以通過lv.setSelection(listView.getPosition)方法。
-
listview如何優(yōu)化圖片淹魄?圖片錯亂的問題是如何產(chǎn)生的诗轻;
-
圖片處理的方法有以下幾種:
- 不要直接拿路徑去循環(huán),BitmapFactory.decodeFile,使用Options保存圖片大小揭北,不要加載圖片到內(nèi)存中去。
- 對圖片一定要邊界壓縮吏颖,尤其是大圖搔体,而如果圖片是后臺服務(wù)器處理好的就不用了。
- 在listview中取圖片的時候不要直接拿路徑去取半醉,而是使用lruCache對圖片做緩存處理疚俱;
- 在getView中做圖片轉(zhuǎn)換的時候,產(chǎn)生的中間變量一定要釋放缩多。
-
圖片錯亂的原因分析: 圖片錯亂的本質(zhì)是由于在listview的時候使用了緩存ConvertView導(dǎo)致的呆奕,假設(shè)一種場景养晋,一個listview一屏只能顯示十條item,那么在拉出第11條item的時候梁钾,這條item其實(shí)是復(fù)用的第一條item绳泉,也就是說第一條item從服務(wù)端下載的圖片,并最重要顯示的時候姆泻,其實(shí)該item已經(jīng)不再當(dāng)前顯示的區(qū)域內(nèi)了零酪,此時顯示的結(jié)果可能在第11條item上輸出圖像,這就導(dǎo)致了圖片錯亂的問題拇勃。解決的方案就是通過給圖片設(shè)置tag來防止圖片錯亂四苇。在getView的時候,給viewHolder類中的imageView設(shè)置一個Tag,這個tag設(shè)置的是圖片的url地址方咆,然后在異步加載圖片完成回調(diào)的方法中月腋,使用findviewWithTag(String url)來找到listview中position對應(yīng)的imageview。然后給imageview設(shè)置圖片即可瓣赂。前提需要預(yù)設(shè)一張圖片榆骚。
//給imageView設(shè)置一個tag。 holder.img.setTag(imgUrl); // 預(yù)設(shè)一個圖片 holder.img.setImageResource(R.drawable.ic_launcher); if (imgUrl != null && !imgUrl.equals("")) { Bitmap bitmap = imageLoader.loadImage(holder.img, imgUrl, new ImageDownloadedCallBack() { @Override public void onImageDownloaded(ImageView imageView, Bitmap bitmap) { // 通過 tag 來防止圖片錯位 if (imageView.getTag() != null && imageView.getTag().equals(imgUrl)) { imageView.setImageBitmap(bitmap); } } }); if (bitmap != null) { holder.img.setImageBitmap(bitmap); } }
-
-
scrollView中如何嵌套listview钩述;
- 通常情況下寨躁,在scrollView 重視不嵌套listview的,但是面試官要是問到這種問題的時候牙勘,回答是可以的职恳,在scrollview 中添加一個listview會導(dǎo)致listview控件顯示不全,通常只會顯示一條方面,這是由于兩個控件的滑動沖突導(dǎo)致的放钦,所以:
- 需要通過listview的item數(shù)量去計(jì)算listview的顯示高度,從而使其完整顯示恭金;
lv = (ListView) findViewById(R.id.lv); adapter = new MyAdapter(); lv.setAdapter(adapter); setListViewHeightBasedOnChildren(lv); ---------------------------------------------------- public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); params.height += 5; //如果沒有這個聲明操禀,listview就只有一點(diǎn)。 listView.setLayoutParams(params); } //而現(xiàn)階段最好的方法就是自定義listview横腿,重寫OnMeasure( )方法颓屑,使其完整顯示。 public class ScrollViewWithListView extends ListView { public ScrollViewWithListView(android.content.Context context, android.util.AttributeSet attrs) { super(context, attrs); } /** * Integer.MAX_VALUE >> 2,如果不設(shè)置耿焊,系統(tǒng)默認(rèn)設(shè)置是顯示兩條 */ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
- 通常情況下寨躁,在scrollView 重視不嵌套listview的,但是面試官要是問到這種問題的時候牙勘,回答是可以的职恳,在scrollview 中添加一個listview會導(dǎo)致listview控件顯示不全,通常只會顯示一條方面,這是由于兩個控件的滑動沖突導(dǎo)致的放钦,所以:
-
如何刷新listview中item的單個數(shù)據(jù)揪惦,不刷新整個listview的數(shù)據(jù)?
- 修改單個item的數(shù)據(jù)罗侯,然后調(diào)用adapter的notifyDataSetChanged()方法進(jìn)行刷新器腋。或者直接用handler去更新,在adapter中創(chuàng)建一個handler纫塌,值發(fā)生改變的時候诊县,handler就send一個message,更新ui措左。
recyclerView:
-
使用recycleView的好處依痊;
- recycleView是Android 5.0 materials design 中的組件之一,recycleView封裝了viewHolder的回收復(fù)用機(jī)制媳荒,也就是說recycleView標(biāo)準(zhǔn)化了viewHolder抗悍,編寫Adapter面向的是viewHolder而不再是view了,復(fù)用的邏輯被封裝了钳枕,寫起來更方便了缴渊。recycleView提供了一種插拔式的體驗(yàn),高度的解耦鱼炒,異常的靈活衔沼,針對一個Item的顯示RecylerView專門抽取出了相應(yīng)的類,來控制Item的顯示昔瞧,使其的擴(kuò)展性非常強(qiáng)指蚁。例如:你想控制橫向或者縱向滑動列表效果可以通過LinearLayoutManager這個類來進(jìn)行控制(與GridView效果對應(yīng)的是GridLayoutManager,與瀑布流對應(yīng)的還有StaggeredGridLayoutManager等),也就是說RecylerView不再拘泥于ListView的線性展示方式自晰,它也可以實(shí)現(xiàn)GridView的效果等多種效果凝化。你想控制Item的分隔線,可以通過繼承RecylerView的ItemDecoration這個類酬荞,然后針對自己的業(yè)務(wù)需求去抒寫代碼搓劫。
可以控制Item增刪的動畫,可以通過ItemAnimator這個類進(jìn)行控制混巧,當(dāng)然針對增刪的動畫枪向,RecylerView有其自己默認(rèn)的實(shí)現(xiàn)。
- recycleView是Android 5.0 materials design 中的組件之一,recycleView封裝了viewHolder的回收復(fù)用機(jī)制媳荒,也就是說recycleView標(biāo)準(zhǔn)化了viewHolder抗悍,編寫Adapter面向的是viewHolder而不再是view了,復(fù)用的邏輯被封裝了钳枕,寫起來更方便了缴渊。recycleView提供了一種插拔式的體驗(yàn),高度的解耦鱼炒,異常的靈活衔沼,針對一個Item的顯示RecylerView專門抽取出了相應(yīng)的類,來控制Item的顯示昔瞧,使其的擴(kuò)展性非常強(qiáng)指蚁。例如:你想控制橫向或者縱向滑動列表效果可以通過LinearLayoutManager這個類來進(jìn)行控制(與GridView效果對應(yīng)的是GridLayoutManager,與瀑布流對應(yīng)的還有StaggeredGridLayoutManager等),也就是說RecylerView不再拘泥于ListView的線性展示方式自晰,它也可以實(shí)現(xiàn)GridView的效果等多種效果凝化。你想控制Item的分隔線,可以通過繼承RecylerView的ItemDecoration這個類酬荞,然后針對自己的業(yè)務(wù)需求去抒寫代碼搓劫。
-
recycleView的使用方法:
recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this ); //設(shè)置布局管理器 recyclerView.setLayoutManager(layoutManager); //設(shè)置為垂直布局咧党,這也是默認(rèn)的 layoutManager.setOrientation(OrientationHelper. VERTICAL); //設(shè)置Adapter recyclerView.setAdapter( recycleAdapter); //設(shè)置分隔線 recyclerView.addItemDecoration(new DividerGridItemDecoration(this )); //設(shè)置增加或刪除條目的動畫 recyclerView.setItemAnimator( new DefaultItemAnimator());
-
recylerView的Adapter的寫法,需要實(shí)現(xiàn)三個方法:
- onCreateViewHolder():這個方法主要生成為每個Item inflater出一個View秘蛔,但是該方法返回的是一個ViewHolder。該方法把View直接封裝在ViewHolder中傍衡,然后我們面向的是ViewHolder這個實(shí)例深员,當(dāng)然這個ViewHolder需要我們自己去編寫。直接省去了當(dāng)初的convertView.setTag(holder)和convertView.getTag()這些繁瑣的步驟蛙埂。
- onBindViewHolder():這個方法主要用于適配渲染數(shù)據(jù)到View中辨液。方法提供給你了一個viewHolder,而不是原來的convertView箱残。
- getItemCount():這個方法就類似于BaseAdapter的getCount方法了,即總共有多少個條目。
-
給RecyclerView的Item添加點(diǎn)擊事件:
- 由于recylerView沒有提供類似于listview的setOnItemClickListener()的方法來處理item的點(diǎn)擊事件,因此只能模擬類似的方法, 使用的是在創(chuàng)建itemView的時候添加監(jiān)聽,就是在創(chuàng)建view的時候添加點(diǎn)擊事件,然后在Adapter對對象中添加監(jiān)聽回調(diào). 具體的做法是:首先自定義接口onRecylerViewItemClickListener,定義onItemClick()方法,在給方法中有兩個參數(shù),view和position,在給holder傳入onRecylerViewItemClickListener參數(shù),讓holder實(shí)現(xiàn)View.OnClickListener,并在onClick方法中調(diào)用onRecylerViewItemClickListener.onItemClick()方法,通過傳入的position來判斷item的位置,從而實(shí)現(xiàn)每個item的點(diǎn)擊事件.
-
給RecyclerView的Item添加下拉刷新:
- 通過SwipeRefreshLayout這個組件,去實(shí)現(xiàn)列表下拉刷新功能,通過設(shè)置下拉刷新的監(jiān)聽事件setOnRefreshListener()重寫OnRefresh()方法,而設(shè)置上拉加載更多可以通過設(shè)置滑動事件監(jiān)聽來實(shí)現(xiàn)setOnScrollListener()重寫onScrollStateChanged()方法.通過設(shè)置swipeRefreshView.setRefreshing為true來實(shí)現(xiàn)刷新.
socket通信與網(wǎng)絡(luò)編程(TCP/UDP協(xié)議被辑,http協(xié)議)
-
什么是網(wǎng)絡(luò)編程:
- 網(wǎng)絡(luò)編程是指兩臺設(shè)備之間實(shí)現(xiàn)數(shù)據(jù)傳遞的過程燎悍,也可以說是使用套接字完成不同進(jìn)程之間的網(wǎng)絡(luò)通訊的編程。要了解網(wǎng)絡(luò)編程盼理,需要先了解網(wǎng)絡(luò)通訊谈山,網(wǎng)絡(luò)通訊分HTTP通訊和socket網(wǎng)絡(luò)通訊,說到這需要先了解一下網(wǎng)絡(luò)通訊的層級宏怔,網(wǎng)絡(luò)通訊的層級一共有四層:最低層鏈路層奏路,這里主要是硬件的接口,然后是網(wǎng)絡(luò)層臊诊,這里用我們比較熟悉的IP協(xié)議鸽粉,在然后是傳輸層,這里有TCP協(xié)議和UDP協(xié)議抓艳,最后就是應(yīng)用層触机,HTTP協(xié)議(超文本傳輸協(xié)議)就在這一層,這里需要注意的是玷或,HTTP是一種協(xié)議儡首,而socket是一個接口。
-
傳輸層兩大協(xié)議:TCP/UDP協(xié)議:
- UDP協(xié)議是一種用戶數(shù)據(jù)報(bào)協(xié)議偏友,是面向無連接的蔬胯,數(shù)據(jù)傳輸不可靠的一種點(diǎn)對多點(diǎn)的通訊,也就是說UDP在傳輸數(shù)據(jù)前是不與對方建立連接的位他,對于接收到的數(shù)據(jù)也是不發(fā)送確認(rèn)信號的氛濒,發(fā)送數(shù)據(jù)的一方也不會知道數(shù)據(jù)是否發(fā)送成功棱诱,也就無法再重新發(fā)送了泼橘。我們經(jīng)常使用的“ping”命令來檢測兩臺設(shè)備主機(jī)之間的TCP/IP通信是否正常,而這個“ping”就是 使用UDP協(xié)議迈勋,通過向?qū)Ψ街鳈C(jī)發(fā)送UDP數(shù)據(jù)包炬灭,然后對方確認(rèn)收到數(shù)據(jù)包,如果對方將數(shù)據(jù)包到達(dá)的纖細(xì)及時的返回回來靡菇,就說明兩臺設(shè)備主機(jī)之間的通訊是通的重归。
- TCP協(xié)議是一種傳輸控制協(xié)議,它是面向有連接的厦凤,數(shù)據(jù)傳輸可靠的一種通訊方式鼻吮,它是通過三次握手來實(shí)現(xiàn)面向有連接的,而這三次握手指的是:
- 首先客戶端發(fā)送一個空的數(shù)據(jù)報(bào)包給服務(wù)端较鼓,并且將客戶端置為發(fā)送狀態(tài)椎木;
- 接著服務(wù)端接收到這這個空的數(shù)據(jù)報(bào)包违柏,會相應(yīng)客戶端一個確認(rèn)包,并將服務(wù)端置為接收狀態(tài)香椎;
3)客戶端接收到服務(wù)端發(fā)送回來的響應(yīng)漱竖,然后再向服務(wù)端發(fā)送一個確認(rèn)包,一旦此包發(fā)送完畢畜伐,那么服務(wù)端就與客戶端之間建立了長連接馍惹,并且雙方都處于確認(rèn)狀態(tài),而建立的這個長連接在理論上如果單方不主動去停止這個連接玛界,這個連接就會一直存在万矾,只要連接存在,服務(wù)器就可以和客戶端近行數(shù)據(jù)的互傳慎框。
-
什么是socket通信:
- 說起socket良狈,得要先知道套接字,套接字是TCP/IP網(wǎng)絡(luò)通信的基本操作單元鲤脏,主要包括三大要素:IP们颜,協(xié)議,端口猎醇。在說socket窥突,socket其實(shí)就是一堆套接字,它在客戶端叫clientSocket硫嘶,在服務(wù)端叫serviceSocket,socket其實(shí)就是方便TCP和UDP編程的一個接口阻问,應(yīng)用層和傳輸層通過socket接口,區(qū)分來自不同的應(yīng)用進(jìn)程和網(wǎng)絡(luò)連接的通信沦疾,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)称近。(應(yīng)用層在通過傳輸層傳輸?shù)臅r候,傳輸層的TCP會同時遇到為多個應(yīng)用進(jìn)程提供并發(fā)服務(wù)的問題哮塞,多個TCP連接或多個應(yīng)用進(jìn)程可能需要同一個TCP連接刨秆,為了區(qū)別不同應(yīng)用進(jìn)程的連接,許多計(jì)算機(jī)為應(yīng)用進(jìn)程提供了套接字接口)
- socket建立連接:socket是一個接口忆畅,它是可以指定傳輸層協(xié)議的衡未,也就是說當(dāng)他在指定TCP協(xié)議的時候建立的socket連接就是一個TCP連接,需要通過三次握手才能進(jìn)行連接家凯。從廣義上講:socket連接可以這樣講:
- 服務(wù)器監(jiān)聽:說的是服務(wù)器套接字并不指定客戶端套接字缓醋,它處于一個實(shí)時監(jiān)聽網(wǎng)絡(luò)狀態(tài),等待客戶端的請求绊诲,連接送粱。
- 客戶端發(fā)送請求:客戶端套接字在請求中聲明套接字的描述和服務(wù)端的ip和端口號,然后向服務(wù)端套接字發(fā)送請求掂之。
- 連接確認(rèn):服務(wù)端套接字接收到客戶端套接字發(fā)送來的請求后抗俄,想客戶端套接字發(fā)送一個確認(rèn)響應(yīng)脆丁,并在這個響應(yīng)中添加服務(wù)器套接字的描述,一旦客戶端確認(rèn)了這個描述橄镜,那么雙方就正式的建立了連接偎快,而測試服務(wù)器處于一個監(jiān)聽狀態(tài),等待著其他客戶端套接字發(fā)送來的請求洽胶。
-
socket接口是如何利用代碼實(shí)現(xiàn)TCP連接和UDP連接的;
- 代碼實(shí)現(xiàn)TCP連接:首先在客戶端創(chuàng)建socket對象裆馒,然后創(chuàng)建inputStream封裝要傳輸?shù)臄?shù)據(jù)姊氓,然后在socket中通過getOutputStream獲取輸出流,然后通過寫出io流的形式將數(shù)據(jù)寫入到服務(wù)器當(dāng)中去喷好。在服務(wù)器中創(chuàng)建serviceSocket對象翔横,然后通過serviceSocket對象中的accept方法獲取socket對象,最后在socket對象中通過getInputStream方法獲取數(shù)據(jù)梗搅。
- 代碼實(shí)現(xiàn)UDP連接: 首先在客戶端創(chuàng)建DatagramSocket對象,然后創(chuàng)建DatagramPacket對象(他其實(shí)就是報(bào)包),這個對象創(chuàng)建的時候會需要傳入四個參數(shù),
DatagramPacket p = new DatagramPacket(messageByte, msg_length, url, server_port);
第一個參數(shù)為傳遞的數(shù)據(jù)data(不過是個字節(jié)數(shù)組,而且不能超過64k),第二個參數(shù)是數(shù)據(jù)的長度,第三個參數(shù)是網(wǎng)絡(luò)地址(可以通過inetAddress.getByName這個方法傳入一個ip就可以獲得網(wǎng)絡(luò)地址了),第四個參數(shù)是端口號禾唁。 然后socket對象.send(packet對象)發(fā)送報(bào)包就可以了。服務(wù)器端創(chuàng)建DatagramSocket對象,創(chuàng)建兩個參數(shù)的DatagramPacket的空報(bào)包對象(只是創(chuàng)建一個字節(jié)數(shù)組),然后調(diào)用socket對象.receive(packet)來接受數(shù)據(jù),最后調(diào)用packet.getData即可.
-
HTTP通訊:
- http協(xié)議:超文本傳輸協(xié)議无切,手機(jī)常用協(xié)議之一荡短,是基于TCP協(xié)議之上的應(yīng)用層協(xié)議。http1.0的時候是一個請求一個連接哆键,請求結(jié)束后就會斷開連接掘托。http1.1的時候是已連接對應(yīng)多個請求,多個請求可以重接執(zhí)行籍嘹,不用等一個請求結(jié)束在進(jìn)行下一個請求闪盔,而http2.0同樣是一個連接對應(yīng)多個請求,并且在應(yīng)用層和傳輸層增加了一個二進(jìn)制的分幀層辱士,這些幀對應(yīng)邏輯流中的消息泪掀,并行的在同一個TCP連接上進(jìn)行雙向交流消息。
-
socket和http的區(qū)別;
- 形象的說http他就像一個轎車,提供了封裝或者顯示數(shù)據(jù)的具體形式,而socket是發(fā)動機(jī),提供了網(wǎng)絡(luò)通訊的能力,http他是一個協(xié)議,是基于TCP協(xié)議的,Tcp協(xié)議是基于ip協(xié)議的,而socket提供了針對TCP和UDP編程的接口颂碘。