android技術方案
Ⅰ 關於Android 消息推送,有什麼開源的技術方案
關於Android 消息推送,採用第三方服務推送。客戶端只需要導入第三方提供的lib庫,有第三方管理長連接,負責消息的接收/發送。同時對消息都有比較詳細的報表數據,可以用於做數據分析、挖掘,改善用戶體驗。第三方服務平台極光推送就不錯。極光推送個性化推送滿足用戶多種推送需要,有效提升用戶體驗,利用大數據人工智慧技術,實現智能用戶分群,提升消息點擊率,推送安全包確保推送內容准確,拒絕運營事故。
???極光推送產品優勢:
1、便捷的使用體驗 快速集成SDK,簡單易用的控制台和API
?2、靈活的目標篩選 提供用戶自定義的標簽和別名系統,以及極光自己根據數據分析出的分類目標
?3、高效穩定的系統 支持10億級的高並發訪問,多點備份保證系統穩定
? 4、專業的支持 有專業的技術支持團隊,及時響應客戶的需求和問題
極光推送搭建起一個高度穩定、可擴展的雲端架構,極大地幫助移動應用開發者節約開發和維護的成本,輕松實現毫秒級的精準推送。
Ⅱ 關於 Android消息推送,有什麼開源的技術方案
安卓消息推送的實現方案有下面幾種:MQTT協議實現
XMPP協議實現
C2DM雲端推送功能(google官方提供,系統內置,但是國內用不了......)
中國統一推送(工信部牽頭成立,但是目前只是開了幾次會議,並沒有什麼實際的介面出來,不過以後應該會是中國境內的首選方案)
選擇第三方消息推送平台,例如極光,個推等,極光成立於2011年,是國內最早開始做開發者服務的一批公司,極光推送的穩定性和送達率一直是業內做的比較好的,具體可以到極光官網了解
Ⅲ 用android會遇到什麼關鍵技術問題及可行性解決方案
1.資源訪問
我們知道,宿主程序調起未安裝的插件apk,一個很大的問題就是資源如何訪問,具體來說就是插件中凡是以R開頭的資源都不能訪問了。這是因為宿主程序中並沒有插件的資源,所以通過R來載入插件的資源是行不通的,程序會拋出異常:無法找到某某id所對應的資源。
針對這個問題,有人提出了將插件中的資源在宿主程序中也預置一份,這雖然能解決問題,但是這樣就會產生一些弊端。首先,這樣就需要宿主和插件同時持有一份相同的資源,增加了宿主apk的大小;其次,在這種模式下,每次發布一個插件都需要將資源復制到宿主程序中,這意味著每發布一個插件都要更新一下宿主程序,這就和插件化的思想相違背了。
因為插件化的目的就是要減小宿主程序apk包的大小,同時降低宿主程序的更新頻率並做到自由裝載模塊,所以這種方法不可取,它限制了插件的線上更新這一重要特性。還有人提供了另一種方式,首先將插件中的資源解壓出來,然後通過文件流去讀取資源,這樣做理論上是可行的,但是實際操作起來還是有很大難度的。首先不同資源有不同的文件流格式,比如圖片、XML等,其次針對不同設備載入的資源可能是不一樣的,如何選擇合適的資源也是一個需要解決的問題,基於這兩點,這種方法也不建議使用,因為它實現起來有較大難度。為了方便地對插件進行資源管理,下面給出一種合理的方式。
我們知道,Activity的工作主要是通過ContextImpl來完成的,
Activity中有一個叫mBase的成員變數,它的類型就是ContextImpl。注意到Context中有如下兩個抽象方法,看起來是和資源有關的,實際上Context就是通過它們來獲取資源的。這兩個抽象方法的真正實現在ContextImpl中,也就是說,只要實現這兩個方法,就可以解決資源問題了。
/** Return an AssetManager instance for your application's package. */
public abstract AssetManager getAssets();
/** Return a Resources instance for your application's package. */
public abstract Resources getResources();
下面給出具體的實現方式,首先要載入apk中的資源,如下所示。
protected void loadResources() {
try {
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, mDexPath);
mAssetManager = assetManager;
} catch (Exception e) {
e.printStackTrace();
}
Resources superRes = super.getResources();
mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),
superRes.getConfiguration());
mTheme = mResources.newTheme();
mTheme.setTo(super.getTheme());
}
從loadResources()的實現可以看出,載入資源的方法是通過反射,通過調用AssetManager中的addAssetPath方法,我們可以將一個apk中的資源載入到Resources對象中,由於addAssetPath是隱藏API我們無法直接調用,所以只能通過反射。下面是它的聲明,通過注釋我們可以看出,傳遞的路徑可以是zip文件也可以是一個資源目錄,而apk就是一個zip,所以直接將apk的路徑傳給它,資源就載入到AssetManager中了。然後再通過AssetManager來創建一個新的Resources對象,通過這個對象我們就可以訪問插件apk中的資源了,這樣一來問題就解決了。
/**
* Add an additional set of assets to the asset manager. This can be
* either a directory or ZIP file. Not for use by applications. Returns
* the cookie of the added asset, or 0 on failure.
* {@hide}
*/
public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
makeStringBlocks(mStringBlocks);
return res;
}
}
接著在代理Activity中實現getAssets()和getResources(),如下所示。關於代理Activity的含義請參看DL開源插件化框架的實現細節,這里不再詳細描述了。
@Override
public AssetManager getAssets() {
return mAssetManager == null ? super.getAssets() : mAssetManager;
}
@Override
public Resources getResources() {
return mResources == null ? super.getResources() : mResources;
}
通過上述這兩個步驟,就可以通過R來訪問插件中的資源了。
2.Activity生命周期的管理
管理Activity生命周期的方式各種各樣,這里只介紹兩種:反射方式和介面方式。反射的方式很好理解,首先通過java的反射去獲取Activity的各種生命周期方法,比如onCreate、onStart、onResume等,然後在代理Activity中去調用插件Activity對應的生命周期方法即可,如下所示。
@Override
protected void onResume() {
super.onResume();
Method onResume = mActivityLifecircleMethods.get("onResume");
if (onResume != null) {
try {
onResume.invoke(mRemoteActivity, new Object[] { });
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void onPause() {
Method onPause = mActivityLifecircleMethods.get("onPause");
if (onPause != null) {
try {
onPause.invoke(mRemoteActivity, new Object[] { });
} catch (Exception e) {
e.printStackTrace();
}
}
super.onPause();
}
使用反射來管理插件Activity的生命周期是有缺點的,一方面是反射代碼寫起來比較復雜,另一方面是過多使用反射會有一定的性能開銷。下面介紹介面方式,介面方式很好地解決了反射方式的不足之處,這種方式將Activity的生命周期方法提取出來作為一個介面(比如叫DLPlugin),然後通過代理Activity去調用插件Activity的生命周期方法,這樣就完成了插件Activity的生命周期管理,並且沒有採用反射,這就解決了性能問題。同時介面的聲明也比較簡單,下面是DLPlugin的聲明:
public interface DLPlugin {
public void onStart();
public void onRestart();
public void onActivityResult(int requestCode, int resultCode, Intent
data);
public void onResume();
public void onPause();
public void onStop();
public void onDestroy();
public void onCreate(Bundle savedInstanceState);
public void setProxy(Activity proxyActivity, String dexPath);
public void onSaveInstanceState(Bundle outState);
public void onNewIntent(Intent intent);
public void onRestoreInstanceState(Bundle savedInstanceState);
public boolean onTouchEvent(MotionEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);
public void onWindowAttributesChanged(LayoutParams params);
public void onWindowFocusChanged(boolean hasFocus);
public void onBackPressed();
…
}
在代理Activity中只需要按如下方式即可調用插件Activity的生命周期方法,這就完成了插件Activity的生命周期的管理。
...
@Override
protected void onStart() {
mRemoteActivity.onStart();
super.onStart();
}
@Override
protected void onRestart() {
mRemoteActivity.onRestart();
super.onRestart();
}
@Override
protected void onResume() {
mRemoteActivity.onResume();
super.onResume();
}
...
通過上述代碼應該不難理解介面方式對插件Activity生命周期的管理思想,其中mRemoteActivity就是DLPlugin的實現。
Ⅳ Android無線開發的幾種常用技術(阿里巴巴資深
完整的開發一個android移動App需要經過從分解需求、架構設計到開發調試、測試、上線發布等多個階段,在發布後還會有產品功能上的迭代演進,此外還會面對性能、安全、無線網路質量等多方面的問題。
移動App的產品形態各不相同,有的是內容類,有的是工具類,有的是社交類,所以它們的業務邏輯所偏重的核心技術有些差別,但它們都會用到一些常用的技術方案。今天我們就先來簡單介紹一下這些常用技術,以後會專門分專題來詳細介紹這些技術的原理和使用場景。
1. Multidex
在Dalvik虛擬機所使用的dex文件格式中,用原生類型short來索引文件中的方法數,也就是最多隻能有4個位元組65536個method,在打包apk的過程中會把工程所需要的全部class文件都合並壓縮到一個dex文件中,也就是說自己開發的代碼加上外部引用的庫的方法總數不能超過65535。
隨著業務邏輯的不斷增長,很容易就會超過這個限制,在編譯期間就會遇到這樣一個錯誤:
還好google官方給出了一個解決方案Multidex,它會把dex文件拆成兩個或多個,第二個dex文件叫classes2.dex,在Application實例化後會從apk中解壓出classes2.dex並將其拷貝到應用的目錄下,通過反射將其注入到當前的ClassLoader中。但是這個方案非但不能解決一切問題也不能直接拿來用,而要加入自己的一些改造,來解決NoClassDefFoundError、INSTALL_FAILED_DEXOPT等問題,以保證自己的dex被順利的載入流暢的執行。
2. Plugin
Multidex雖然可以解決方法數的限制,但隨著業務邏輯越來越多,apk的大小也變得越來越多,而且有一些功能並非全部用戶都想用的,所以會把一些功能模塊獨立出來做成插件,讓用戶可以按需下載更新,這樣既減小了包大小,又改善了用戶體驗。
插件類似於windows的dll文件,放在某個特定目錄,應用程序主框架會用LoadLibrary載入各dll文件,按插件介面去訪問插件。Android的插件技術也是這樣,利用一個進程可以運行多個apk的機制,用ClassLoader將宿主apk之外的類載入進來,插件的context可以通過createPackageContext方法創建。因為插件中的activity,service等組件如果沒有在AndroidManifest.xml中聲明將不能運行,所以需要預先在AndroidManifest.xml中聲明一個代理類(ProxyActivity),將這個ProxyActivity傳給插件,讓插件的activity也有訪問資源的能力。
3. Hot Patch
有時一些嚴重的crash bug或漏洞需要緊急修復,但有些用戶不會或不願意立即升級,而且頻繁升級,沒有特別的功能更新只是修復bug的升級,對活躍用戶是一種傷害。熱補丁就可以解決這樣的窘境,它是一種可以線上修復的技術方案,有動態改變方法的能力,一般大型的移動應用都會使用熱補丁來處理緊急事件。
Hot Patch可以通過hook來修改java的method,注入自己的代碼,實現非侵入式的runtime修改,或者採用正向編程,通過工具生成patch文件,通過jni bridge指向補丁文件中的方法。還有就是利用ClassLoader,在dex中查找class時,如果找到類則返回,找不到就從下一個dex文件中繼續查找,由此可以想到,在把問題修復後,可以單獨生成一個dex,通過反射插入到dexElements數組的最前面,這樣就能讓dalvik載入補丁里的類了。
4. Push通道
Push是移動App常用的一種無線技術,基礎是基於TCP的心跳機制,和客戶端維持一個長連接。用處是向客戶端推送消息,或者代替客戶端定時去從伺服器pull的策略,改為客戶端接收到push消息後再去pull。
如果每個應用都自己實現push通道的話,cpu就會不定時地經常被喚醒,耗電量達到難以容忍的程度,而且自己搭建push平台的成本也很大,實時性和效率也存在問題,一般都直接使用一些服務商提供的push方案,這些push平台一般都經過了優化設計,在跨平台和網路穿透性、長連接心跳包、多客戶端App鏈路復用、服務和連接保活等技術上做了優化。比如Agoo最初是淘寶無線事業部開發的push服務,在逐漸完善和支撐淘系其他app後,通過服務端容量、通訊協議優化、業務和開放能力的拓展改進後,與友盟等合作,開始向第三方提供推送服務。
5. 應用加固
一款熱門的移動app或游戲發布後會受到很多的關注,經常會遇到二次打包的盜版行為,破解者要麼修改游戲的資源文件、道具、分值甚至直接把訪問的站點指向自己架設的伺服器,損害了開發者的利益;要麼偷偷植入自己的惡意代碼,表面上看起來跟正版的app完全一樣,在後台卻盜取用戶隱私,植入木馬;要麼通過反向工程學習原app的核心技術,打破技術上的競爭壁壘。
為了防止被破解只通過混淆是遠遠不夠的,即使是在native層混淆也還是會被人熟練的反編譯,所以需要一套對apk的保護方案來反調試、防逆向和防篡改。一般的加固方法都是對原apk先進行加密,然後和殼合並生成新的apk。殼是用來解密apk的dex文件。當應用啟動時,殼先解密原apk,准備好自己定義的ClassLoader,然後獲取源程序中的Application名稱,通過反射找到正確的Application對象,運行它的onCreate方法,這樣原apk才能被真正運行。其他一些反調試的方法有針對反編譯工具,在源程序中加入一些無效的指令或無效的指針,引發反編譯工具的崩潰,還有就是加花指令,利用一些跳轉,堆棧操作等指令,讓破解者無法清楚地理解反匯編後的內容。
6. 其他
除了上述幾點外,在服務端還會涉及灰度策略、鏈路流量優化、動態更新配置、防DNS劫持等技術,在客戶端會涉及用戶埋點上報、在線監控、進程保活、H5和native混合開發、注入框架等。
Ⅳ android 需要具備什麼技術
android開發任職要求:
1.Android/iphone平台手機終端軟體開發精通Android開發平台及框架,一年以上實際開發經驗;
2.精通Android GUI程序開發;
3.1年以上J2ME開發經驗,熟悉J2ME編程;熟悉Linux環境編程優先 ;從事過嵌入式開發工作2年以上。
4.熟悉HTML/WML/HTTP,具有良好的編程思想;
5.熟悉C/C++或者Java開發語言和環境;
6.有一年以上移動終端應用軟體開發經驗,有Android或者iPhone開發經驗尤佳;
7.基礎扎實,精通常用數據結構與演算法和設計能力;
8.熟悉移動終端特性和開發特點; 熟悉移動終端網路編程,了解3G\WiFi等技術;
9.熟悉C++/C#, MSSQL/MySQL資料庫開發;熟悉多線程、Socket或ACE等網路通信編程技術;
10.熟悉java各種編程方法,比如多線程,jni,idl等。 熟悉JVM的運行機制,移植或者擴展過JVM到嵌入式平台者優先,比如phoneme 等。
11.精通Android平台UI開發優先;英語良好,能閱讀英文資料;
工作職責:
1.負責Android平台的瀏覽器開發。
2.在Android手機上設計並開發應用程序或游戲;
3.Android平台框架層的維護以及擴展。
4.移植各種流行的框架體系(多媒體,藍牙,無線)到android上負責Android項目的開發工作;
5.負責Android項目的架構設計、方案的制定;
6.跟進Android的新技術發展。纂寫設計開發及實現文檔;
7.根據產品功能需求設計並完成軟體實現;
8.參與產品需求分析並制定技術實施方案;
Ⅵ Android系統原理及開發要點詳解的前 言
Android 是Google歷經數年和投資數億美元開發出來的智能手機系統,Google也發起了圍繞Android的組織——開放手機聯盟,其英文全稱為「Open Handset Alliance」。
隨著各大移動終端生產商大力開發和生產基於Android的移動智能設備,Android迅速得到業界和社會的認可,並成為整個產業的熱點,基於Android平台的各類人才逐漸成為各大企業競相爭奪的焦點。
Android系統是一個開放的系統,任何公司、個人開發者、愛好者都可以參與其中。對於技術工作者,Android不僅是一個智能手機的系統,也可以作為學習嵌入式Linux系統的較完整的軟體平台。
Android是一個較新的系統和技術,因此介紹Android的資料和書籍還比較少,尤其簡體中文的書籍,相對更少。本書《Android系統原理及開發要點詳解》 是一本綜合介紹Android系統的書,集合了Androidin社區多位專家作者的經驗,精心編寫而成。
Android 作為一個龐大的系統,包括了Linux操作系統、各種本地程序、虛擬機和運行環境、Java框架和Java應用程序多方面的內容。這對於初學者是一個非常大的挑戰,因此對於學習、研究進而開發Android系統來說,掌握系統的脈絡和使用恰當的學習方法是非常重要的,這也是本書的組織主旨。
本書特點
為了適應Android系統的情況,本書在內容的編排和組織上具有以下一些重要特點。
保持完整性和層次性
本書緊緊把握Android系統的4個層次,分章節介紹,並且有重點地介紹了Android整個系統的代碼結構、編譯系統、相關工具、各部分組織等全局性內容。這將讓讀者即使只花費較短的時間,也可以獲得對Android系統大致的感性理解。
提供清晰的框架
Android是一個有數百兆大小的較大系統,各部分之間是有機聯系的,這就要求Android的學習和開發者需要具有一些軟體架構方面的知識。本書為Android整體和重點模塊繪制了大量的框圖,這樣非常有利於幫助讀者直觀地理解系統。本書在講述每一個部分時,均列出相關代碼的路徑,幫助讀者對應著進行快速、高效地學習。
抓核心內容
Android系統已經發布了若干個版本:1.0、1.5(cupcake)、1.6(donut)和2.0(eclair),從開發的角度,各個版本在同時使用,這對於學習者是一個較大的挑戰。因此本書作者通過把握Android演進中脈絡,盡量總結出共性的內容展示給讀者。在某些部分,在講解代碼的同時,突出概念性的內容。本書力求通過一本教材,給讀者一個長期的、穩定的學習方法和思路。
開發細節
Android 包含眾多的軟體、程序和工具,涉及軟體開發各個方面。在實際的開發過程中,很多內容並不需要開發者去改動。本書從工程的角度出發,偏重開發中常用的內容,對於開發中較少涉及的部分,僅做精煉的大致介紹。本書重點介紹顯示機制、輸入機制、音頻/視頻系統的移植層、多媒體系統的構建、電話系統的構建、連接系統的構建、感測器的移值、應用開發中最常涉及的部分,在每段講解中,穿插了開發中可以使用的一些技巧。
本書內容
本書的各個章節及其組織方式如下所示。
第1章「Android系統概述」,概述Android系統方面的內容,包括智能手機平台的發展歷程、Android系統的特點、Android的3種開發工作,以及Android的2種不同的開發方式。
第2章「Android系統開發綜述」,介紹Android系統開發的綜述性內容,包括工具使用、獲得代碼、編譯系統、模擬器運行、SDK使用等。
第3章「Android的Linux內核與驅動程序」,介紹Android內核的特點、Android中使用的專用驅動程序、Android系統可能使用的標准設備驅動。
第4章「Android的底層庫和程序」,介紹Android系統的基礎程序,以本地程序為主。
第5章「Android的Java虛擬機和Java環境」,這是介於本地和Java層之間的相關內容,主要介紹Android的Java虛擬機Dalvik的基本概念、Android Java程序的環境、JNI的使用方法,以及Java框架的啟動流程等。
第6章「Android的GUI系統」,包括Android GUI系統架構、底層的pixelflinger和libui庫、Surface系統、Skia和2D圖形系統、Android的OpenGL和3D圖形系統等內容。
第7章「Android的Audio系統」,主要是音頻的輸入輸出環節,音頻系統從驅動程序、本地框架到Java框架都具有內容。
第8章「Android的Video輸入輸出系統」,介紹Android的Video輸入輸出系統,包括Overlay系統和Camera系統兩個部分,前者只有本地的內容,後者各個層次均有內容。
第9章「Android的多媒體系統」,介紹Android的多媒體系統的核心部分,包括Android中多媒體系統的業務、結構、多媒體系統的核心框架、OpenCore系統結構和使用等內容。
第10章「Android的電話部分」,介紹Android系統在電話方面的功能,Android是智能手機系統,電話是其核心部分。
第11章「Android的連接部分」,主要包括WiFi、藍牙及定位系統等,這些Android的連接部分也具有從驅動層到Java應用層的結構。
第12章「Android的感測器系統」,感測器系統涉及Android的各個層次,具有完整的結構,相比其他系統,感測器系統的各個層次都比較簡單。
第6~12章分模塊介紹Android的幾個核心系統,主要是本地框架和Java框架方面的內容,兼顧應用程序和驅動層,這是本書的重點。
第13章「Android應用程序概述及框架」,介紹Android應用程序層的基本概念和應用程序框架,這部分內容是Android自下而上的第4個層次,可以基於源代碼或者SDK開發,它們之間的差別非常小。
第14章「Android應用程序的主要方面」,介紹Android應用程序層開發的各個方面,基本上是橫向內容,包括應用程序的基本控制、各種UI元素的使用、圖形API使用3個方面的內容。
第15章「Android應用程序的設計思想」,本章的內容是基於通用的應用程序和GUI程序的通用設計思想,結合Android系統自身的特點,提出一些值得注意的問題和設計方法。
本書讀者
本書適應廣大的讀者群,力求在Android的系統移植、應用程序開發、系統框架改進方面給讀者全面的支持。不同的讀者在學習本書時,應該使用不同的方法。
Android初級開發者:在本書指引下閱讀代碼,搭建系統開發環境,對於Android應用程序的開發者,重點關注後3章的內容。
Android中、高級開發者:通過本書的引導,學習系統架構,關注開發要點,並盡量使用手機系統的通用設計思想、軟體工程思想、系統工程思想來指導Android系統學習。
嵌入式Linux系統學習者:將Android作為一個集Linux核心和應用層程序於一體的系統進行學習,並可以利用Android的模擬環境運行和調試程序。
讀者在學習本書的過程中,應盡量對照本書的框圖和手頭的Android源代碼,這樣可以達到事半功倍的效果。本書在重點代碼中加上大量的注釋,幫助讀者閱讀,對於非重點的代碼,不佔用本書的篇幅,讀者可以參考開放的源代碼。可以採用順序讀和重點讀相結合的方式學習本書,順序讀關注系統框架,重點讀關注開發要點。
本書作者
本書在編寫過程中提煉和綜合Android早期開發者的經驗、中國大陸Androidin社區的開發成果,以及各位專家的經驗和技術,這是本書出版的知識源泉。本書主要由Androidin社區的兩名核心技術專家韓超和梁泉領銜規劃和編著,韓超統稿。總部設在南加州、專注於Android平台並提供其移動應用開發及解決方案的邁奔無線(mAPPn Inc.)也投入技術和人力參與了本書的工作。
參與本書編寫的還有於仕林、張宇、張超等人,趙家維、黃亮、沈楨、徐威特、楊鈺等參與了審校工作。
由於時間倉促,可能依然存在一些錯誤和問題,請讀者見諒,歡迎讀者討論和指點。
Ⅶ 有哪些android開發技巧
1、android:clipToPadding
意思是控制項的繪制區域是否在padding裡面。默認為true。如果你設置了此屬性值為false,就能實現一個在布局上事半功陪的效果。先看一個效果圖。
上圖中的ListView頂部默認有一個間距,向上滑動後,間距消失,如下圖所示。
如果使用margin或padding,都不能實現這個效果。加一個headerView又顯得大材小用,而且過於麻煩。此處的clipToPadding配合paddingTop效果就剛剛好。
同樣,還有另外一個屬性也很神奇:android:clipChildren,具體請參考:【Android】神奇的android:clipChildren屬性
2、match_parent和wrap_content
按理說這兩個屬性一目瞭然,一個是填充布局空間適應父控制項,一個是適應自身內容大小。但如果在列表如ListView中,用錯了問題就大了。ListView中的getView方法需要計算列表條目,那就必然需要確定ListView的高度,onMesure才能做測量。如果指定了wrap_content,就等於告訴系統,如果我有一萬個條目,你都幫我計算顯示出來,然後系統按照你的要求就new了一萬個對象出來。那你不悲劇了?先看一個圖。
假設現在ListView有8條數據,match_parent需要new出7個對象,而wrap_content則需要8個。這里涉及到View的重用,就不多探討了。所以這兩個屬性的設置將決定getView的調用次數。
由此再延伸出另外一個問題:getView被多次調用。
什麼叫多次調用?比如position=0它可能調用了幾次。看似很詭異吧。GridView和ListView都有可能出現,說不定這個禍首就是wrap_content。說到底是View的布局出現了問題。如果嵌套的View過於復雜,解決方案可以是通過代碼測量列表所需要的高度,或者在getView中使用一個小技巧:parent.getChildCount == position
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (parent.getChildCount() == position) {
// does things here
}
return convertView;
}
3、IllegalArgumentException: pointerIndex out of range
出現這個Bug的場景還是很無語的。一開始我用ViewPager + PhotoView(一個開源控制項)顯示圖片,在多點觸控放大縮小時就出現了這個問題。一開始我懷疑是PhotoView的bug,找了半天無果。要命的是不知如何try,老是crash。後來才知道是android遺留下來的bug,源碼里沒對pointer index做檢查。改源碼重新編譯不太可能吧。明知有exception,又不能從根本上解決,如果不讓它crash,那就只能try-catch了。解決辦法是:自定義一個ViewPager並繼承ViewPager。請看以下代碼:
/**
* 自定義封裝android.support.v4.view.ViewPager,重寫onInterceptTouchEvent事件,捕獲系統級別異常
*/
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context context) {
this(context, null);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
LogUtil.e(e);
} catch ( e) {
LogUtil.e(e);
}
return false;
}
}
把用到ViewPager的布局文件,替換成CustomViewPager就OK了。
4、ListView中item點擊事件無響應
listView的Item點擊事件突然無響應,問題一般是在listView中加入了button、checkbox等控制項後出現的。這個問題是聚焦沖突造成的。在android裡面,點擊屏幕之後,點擊事件會根據你的布局來進行分配的,當你的listView裡面增加了button之後,點擊事件第一優先分配給你listView裡面的button。所以你的點擊Item就失效了,這個時候你就要根據你的需求,是給你的item的最外層layout設置點擊事件,還是給你的某個布局元素添加點擊事件了。
解決辦法:在ListView的根控制項中設置(若根控制項是LinearLayout, 則在LinearLayout中加入以下屬性設置)descendantFocusability屬性。
android:descendantFocusability="blocksDescendants"
官方文檔也是這樣說明。
5、getSupportFragmentManager()和getChildFragmentManager()
有一個需求,Fragment需要嵌套3個Fragment。基本上可以想到用ViewPager實現。開始代碼是這樣寫的:
mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getActivity().getSupportFragmentManager(), subFragmentList));
導致的問題是嵌套的Fragment有時會莫名其妙不顯示。開始根本不知道問題出現在哪,當你不知道問題的原因時,去解決這個問題顯然比較麻煩。經過一次又一次的尋尋覓覓,終於在stackoverflow上看到了同樣的提問。說是用getChildFragmentManager()就可以了。真是這么神奇!
mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getChildFragmentManager, subFragmentList));
讓我們看一下這兩個有什麼區別。首先是getSupportFragmentManager(或者getFragmentManager)的說明:
Return the FragmentManager for interacting with fragments associated with this fragment's activity.
然後是getChildFragmentManager:
Return a private FragmentManager for placing and managing Fragments inside of this Fragment.
Basically, the difference is that Fragment's now have their own internal FragmentManager that can handle Fragments. The child FragmentManager is the one that handles Fragments contained within only the Fragment that it was added to. The other FragmentManager is contained within the entire Activity.
已經說得比較明白了。
6、ScrollView嵌套ListView
這樣的設計是不是很奇怪?兩個同樣會滾動的View居然放到了一起,而且還是嵌套的關系。曾經有一個這樣的需求:界面一共有4個區域部分,分別是公司基本信息(logo、名稱、法人、地址)、公司簡介、公司榮譽、公司口碑列表。每部分內容都需要根據內容自適應高度,不能寫死。鄙人首先想到的也是外部用一個ScrollView包圍起來。然後把這4部分分別用4個自定義控制項封裝起來。基本信息和公司簡介比較簡單,榮譽需要用到RecyclerView和TextView的組合,RecyclerView(當然,用GridView也可以,3列多行的顯示)存放榮譽圖片,TextView顯示榮譽名稱。最後一部分口碑列表當然是ListView了。這時候,問題就出來了。需要解決ListView放到ScrollView中的滑動問題和RecyclerView的顯示問題(如果RecyclerView的高度沒法計算,你是看不到內容的)。
當然,網上已經有類似的提問和解決方案了。
給一個網址:
四種方案解決ScrollView嵌套ListView問題
ListView的情況還比較好解決,優雅的做法無非寫一個類繼承ListView,然後重寫onMeasure方法。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
ListView可以重寫onMeasure解決,RecyclerView重寫這個方法是行不通的。
說到底其實計算高度嘛。有兩種方式,一種是動態計算RecycleView,然後設置setLayoutParams;另外一種跟ListView的解決方式類似,定義一個類繼承LinearLayoutManager或GridLayoutManager(注意:可不是繼承RecyclerView),重寫onMeasure方法(此方法比較麻煩,此處不表,下次寫一篇文章再作介紹)。
動態計算高度如下:
int heightPx = DensityUtil.dip2px(getActivity(), (imageHeight + imageRowHeight) * lines);
MarginLayoutParams mParams = new MarginLayoutParams(LayoutParams.MATCH_PARENT, heightPx);
mParams.setMargins(0, 0, 0, 0);
LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(mParams);
honorImageRecyclerView.setLayoutParams(lParams);
思路是這樣的:服務端返回榮譽圖片後,由於是3列顯示的方式,只需要計算需要顯示幾行,然後給定行間距和圖片的高度,再設置setLayoutParams就行了。
int lines = (int) Math.ceil(totalImages / 3d);
至此,這個奇怪的需求得到了解決。
可是在滑動的時候,感覺出現卡頓的現象。聰明的你肯定想到是滑動沖突了。應該是ScrollView的滑動干擾到了ListView的滑動。怎麼辦呢?能不能禁掉ScrollView的滑動?
網路一下,你肯定能搜索到答案的。先上代碼:
/**
* @author Leo
*
* Created in 2015-9-12
* 攔截ScrollView滑動事件
*/
public class CustomScrollView extends ScrollView {
private int downY;
private int touchSlop;
public CustomScrollView(Context context) {
this(context, null);
}
public CustomScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downY = (int) e.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int) e.getRawY();
if (Math.abs(moveY - downY) > touchSlop) {
return true;
}
}
return super.onInterceptTouchEvent(e);
}
}
只要理解了getScaledTouchSlop()這個方法就好辦了。這個方法的注釋是:Distance in pixels a touch can wander before we think the user is scrolling。說這是一個距離,表示滑動的時候,手的移動要大於這個距離才開始移動控制項,如果小於此距離就不觸發移動。
看似很完美了。
但是還有另外一個問題:我每次載入這個界面花的時間太長了,每次由其它界面啟動這個界面時,都要卡上1~2秒,而且因手機性能時間不等。並不是由於網路請求,取數據由子線程做,跟UI線程毫無關系。這樣的體驗自己看了都很不爽。
幾天過去了,還是那樣。馬上要給老闆演示了。這樣的體驗要被罵十次呀。
難道跟ScrollView的嵌套有關?
好吧,那我重構代碼。不用ScrollView了。直接用一個ListView,然後add一個headerView存放其它內容。因為控制項封裝得還算好,沒改多少布局就OK了,一運行,流暢順滑,一切迎刃而解!
本來就是這么簡單的問題,為什麼非得用ScrollView嵌套呢?
stackoverflow早就告訴你了,不要這樣嵌套!不要這樣嵌套!不要這樣嵌套!重要的事情說三遍。
ListView inside ScrollView is not scrolling on Android
當然,從android 5.0 Lollipop開始提供了一種新的API支持嵌入滑動,此時,讓像這樣的需求也能很好實現。
此處給一個網址,大家有興趣自行了解,此處不再討論。
Android NestedScrolling 實戰
7、EmojiconTextView的setText(null)
這是開源表情庫com.rockerhieu.emojicon中的TextView加強版。相信很多人用到過這個開源工具包。TextView用setText(null)完全沒問題。但EmojiconTextView setText(null)後就悲劇了,直接crash,顯示的是null pointer。開始我懷疑時這個view沒初始化,但並不是。那就調試一下唄。
@Override
public void setText(CharSequence text, BufferType type) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
EmojiconHandler.addEmojis(getContext(), builder, mEmojiconSize);
super.setText(builder, type);
}
EmojiconTextView中的setText看來沒什麼問題。點SpannableStringBuilder進去看看,源碼原來是這樣的:
/**
* Create a new SpannableStringBuilder containing a of the
* specified text, including its spans if any.
*/
public SpannableStringBuilder(CharSequence text) {
this(text, 0, text.length());
}
好吧。問題已經找到了,text.length(),不空指針才怪。
text = text == null ? "" : text;
SpannableStringBuilder builder = new SpannableStringBuilder(text);
加一行判斷就行了。
先想到這么多,以後再補充。
Ⅷ Android 開發有哪些新技術出現
參考如下知乎的內容:
開發工具
Android Studio: Google 官方放棄 Eclipse 和 Android Studio 普及。AS 雖然不算新,但是對 Android Studio 這個軟體的更新速度快的驚人,有大量的新功能發布。例如支持很多註解代碼提示註解、Live code template、支持自動生成 Parcelable 實現等等,作為開發者,持續關注這個更新列表 Recent Changes ,一定會讓你的寫代碼的生活更加美好。
編程「語言」
Kotlin: 作為 Android 領域的 Swift,絕對讓你如沐新風。拋棄沉重的 Java 語法,Kotlin 融入了很多現代編程語言的思想,作為開發者,接受新的語言,了解新語言的發展趨勢,更有利於開闊你的思路和加深對語言的理解。在 Android 開發上,使用 Kotlin 並不會讓你付出什麼代價,為什麼不來試試? 使用Kotlin進行Android開發。
React Native: 跨平台一直是程序員的夢想,而且移動應用的跨平台解決方案也很多,因為 Facebook 的參與和力推,讓這個解決方案帶上了光環。第一個用 React Native 開發的 App 已經在 Google Play 上架 Facebook 廣告管理工具,聽說 Android 的 SDK 也馬上會到來,React Native。
Sky: 與 React Native 類似,使用 Web 開發語言來做移動平台的開發,雖然這個只是一個嘗試,但是這是 Google 自身推出的,特別是在 Java 語言的使用上敗訴之後,這可能會有一些作為呢,domokit/sky_sdk · GitHub
開發模式
Dagger 2:依賴注入並不是什麼新技術,但是使用在 Android 確實一個新的嘗試。Android App 越來越被當成嚴肅的大型項目來構建,很多在以前大型伺服器開發上使用的技術都被應用到了移動開發。Android 開發分模塊開發,使用 Dagger 來松耦合模塊。特別值得一體的是,Dagger 2 現在由 Google 親自接管。 Dagger ‡ A fast dependency injector for Android and Java.
MVP:因為 Android 並沒有嚴格的業務和界面區分,項目一復雜,就很容易使代碼陷入混亂。現在 Android 開發社區對 MVP 模式討論越來越熱,覺得 MVP 是非常適合 Android APP 開發。MVP for Android: how to organize the presentation layer
Ⅸ APP開發常用的技術方案有哪些
APP開發是一項高技術含量的工作,通常開發一款成功的APP都是一項龐大的工程,還需要掌握一套完善的技術及編程語言。
首先呢,APP開發一般從技術架構上都會包括後台的管理端,在PC端操作,也就是管理我們整體系統後台。包括用戶、許可權、訂單,還有一些管理的功能。另外就是APP的前端包括iOS和Android,這是一個APP的整體系統架構。
APP開發商的系統一般通用的技術方案,都是前後台分離的。前端用iOS開發語言和Android的開發語言來進行開發,和後端應用層之間是通過介面的方式進行調用,後台負責後台管理端的開發。
技術架構上常用的技術方案無非現在比較流行的是PHP、JAVA,當然還有.NET技術。