編輯:Android資訊
整個框架式不同於androidannotations,Roboguice等ioc框架,這是一個類似spring的實現方式。在整應用的生命周期中找到切入點,然後對activity的生命周期進行攔截,然後插入自己的功能。
如果你想看ui方面的東西,這裡沒有,想要看牛逼的效果這裡也沒有。這只是純實現功能的框架,它的目標是節省代碼量,降低耦合,讓代碼層次看起來更清晰。整個框架一部分是網上的,一部分是我改的,為了適應我的編碼習慣,還有一部分像orm完全是網上的組件。在此感謝那些朋友們。整個框架式的初衷是為了偷懶,之前都是一個功能一個jar,做項目的時候拉進去,這樣對於我來說依然還是比較麻煩。最後就導致我把所有的jar做成了一個工具集合包。有很多框架都含有這個工具集合裡的功能,這些不一定都好用,因為這是根據我個人使用喜歡來實現的,如果你們有自己的想法,可以自己把架包解壓了以後,源碼拉出來改動下。目前很多框架都用到了注解,除了androidannotations沒有入侵我們應用的代碼以外,其他的基本上都有,要麼是必須繼承框架裡面的 activity,要麼是必須在activity的oncreat裡面調用某個方法。整個框架式不同於androidannotations,Roboguice等ioc框架,這是一個類似spring的實現方式。在整應用的生命周期中找到切入點,然後對activity的生命周期進行攔截,然後插入自己的功能。
如果需要混淆 第一步 你要先引入你得架包 -libraryjars libs/android-support-v4.jar -libraryjars libs/loonandroid.jar 第二步 你要保證注解在代碼優化的時候不能被刪除掉 -keepattributes Signature -keepattributes Annotation第三步 support4 要排除掉 -dontwarn android.support.v4.**
-keep class android.support.v4.** { ; }
-keep interface android.support.v4.app.* { ; }
-keep public class * extends android.support.v4.*
-keep public class * extends android.app.Fragment 第四步 只要使用了注解的包名 全部排除掉 -dontwarn xxx.**
-keep class xxx.** { ; }
其中XXX替換成你使用了注解的包名第五步 保證R不被混淆 -keep class *.R$* {
*;
} 即OK
其中分為以下幾種:
舉例:普通activity
public class FourActivity extends Activity { View xx; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main4); xx = find......; //--------------------------------------------------------- 組件的初始化 //--------------------------------------------------------- } }
這其中我們會耗費大量的代碼或者重復性的去些一些代碼。特別是布局比較復雜的情況下。
如果用框架
@InjectLayer(R.layout.activity_main3) public class ThirdActivity extends Activity { @InjectView View xx; }
即可
像軟件的說明頁面,就是單純的展示一個布局,那麼就是
@InjectLayer(R.layout.activity_main3) public class ThirdActivity extends Activity { }
即可
整個ioc框架不需要你繼承任何的acitivity,這樣就保證了不會在你的代碼結構層次上造成影響,因為有的時候你需要自己的BaseActivity來實現你公用的功能。
這種情況下,對於一般的框架來說,做法有以下幾種:
1 ActivityGroup 你不需要繼承任何activity 和普通activity 實現方式(如上面的例子)
2 BaseActivity
見代碼:
首先是BaseActivity @InjectPLayer(R.layout.activity_com) public class BaseActivity extends Activity {}
其中R.layout.activity_com是包括上下導航的布局,中間是一個view子activity只需要這麼寫即可
@InjectLayer(value = R.layout.activity_main, parent = R.id.common) public class MainActivity extends BaseActivity {}
當然 又會有問題了,那麼我上下導航裡面的點擊事件怎麼綁定,怎麼去初始化,難道要每一個子activity都要去寫嗎?當然不需要
@InjectPLayer(R.layout.activity_com) public class BaseActivity extends Activity { @InjectInit private void init() { MeApplication.logger.s("公共類的初始化"); } // 這裡是第一種交互事件注入方式(單擊) @InjectMethod(@InjectListener(ids = { R.id.top, R.id.bottom }, listeners = { OnClick.class })) private void click2(View view) { Handler_TextStyle handler_TextStyle = new Handler_TextStyle(); switch (view.getId()) { case R.id.top: handler_TextStyle.setString("點擊了頂部按鈕(在基類中統一注冊,也可以單獨注冊)"); handler_TextStyle.setBackgroundColor(Color.RED, 3, 5); Toast.makeText(this, handler_TextStyle.getSpannableString(), Toast.LENGTH_LONG).show(); break; case R.id.bottom: handler_TextStyle.setString("點擊了底部按鈕(在基類中統一注冊,也可以單獨注冊)"); handler_TextStyle.setBackgroundColor(Color.RED, 3, 5); Toast.makeText(this, handler_TextStyle.getSpannableString(), Toast.LENGTH_LONG).show(); break; } } }
如上 其中@InjectInit注解表示不管是在子activity還是父activity 都是在布局初始化完成以後才會調用,其先後順序是
父布局layout->子布局layout->父布局ioc和事件綁定->子布局事件綁定。
父activity 中可以對所有的公用組件和事件進行初始化和綁定還沒完,又會有另一個問題,如果我某個頁面下導航的a按鈕和其他頁面底部a按鈕的功能不一樣 要單獨設置怎麼辦。那麼我們可以在子布局進行@InjectMethod和@InjectView進行事件綁定和組件注入,它們會覆蓋父類中相同id的組件的操作以下是view注入的方法說明:
表示是Activity的setContentView
@InjectLayer(value = R.layout.activity_main2, parent = R.id.common, isFull = true, isTitle = true)
其中需要哪個參數就用哪個,value 是必須的 如果只有layout可以這麼寫@InjectPLayer(R.layout.activity_com)。其中value 表示layout,parent表示它在父布局中所對應組件的id 如上圖中 中間顯示區域的view的id。Isfull是否全屏,默認為false.isTitle 是否有標題,默認false;
自動注入view注解。
@InjectView TextView test;
其中test表示它在xml中對應的Id為test
@InjectView(R.id.next2) TextView test;
表示它在xml中對應的Id為next2
@InjectView(binders = { @InjectBinder(method = "click", listeners = { OnClick.class, OnLongClick.class }) }) Button next, next3, next4;
其中表示對id為next,next3,next4進行注解,其中binders 表示綁定了以下事件,binders 是個數組,也就是說可以用多個InjectBinder綁定多個事件,也可以用listeners = { OnClick.class, OnLongClick.class }來表示對組件注入了點擊事件和長按事件
@InjectView(value = R.id.next2, binders = { @InjectBinder(method = "click", listeners = { OnClick.class }) }) Button button;
對於變量名和組件id不一致的view則需要設置value Click 表示那些注入的事件觸發以後所調用的方法,其必須在當前類內。 // 支持由參數和無參數 即click(View view)或者click() 當然click名字必須對於變量注解中的method = “click”
private void click(View view) { switch (view.getId()) { case R.id.next: startActivity(new Intent(this, ThirdActivity.class)); break; ... } }
@InjectResource String action_settings; @InjectResource Drawable ic_launcher;
InjectResource支持string和drawable的注解
// 底部導航欄 子類覆蓋父類
@InjectMethod(@InjectListener(ids = { R.id.bottom }, listeners = { OnClick.class, OnLongClick.class })) private void click3(View view) { Handler_TextStyle handler_TextStyle = new Handler_TextStyle(); handler_TextStyle.setString("點擊了底部按鈕 子類覆蓋了父類"); handler_TextStyle.setBackgroundColor(Color.RED, 3, 5); Toast.makeText(this, handler_TextStyle.getSpannableString(), Toast.LENGTH_LONG).show(); }
@InjectMethod是當我們對一個組件只需要觸發而不需要find出來的時候用到。 ids 表示綁定哪些id,listeners 表示綁定哪些事件 這兩個參數都是數組
當然 如果嫌注解字段太長,可以自己修改。這個是整個view的注入。
@InjectInit void init() { MeApplication.logger.s("子類的初始化"); test.setText("初始化完成,第一個頁面"); }
這個注解你在activity中添加到任何一個方法名上,那麼,當所有的layout和所有的view以及事件綁定完畢以後,會第一個調用含有這個注解的方法。它相當於oncreat
注意:框架注解了整個activity的生命周期, @InjectOnNewIntent,@InjectPause,@InjectResume, @InjectRestart,@InjectStart,@InjectStop 其中OnDestroy無注解。 如果Activity中有含有這些注解的方法 那麼不同生命周期下回自動調用這些方法
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.inflater = inflater; View rootView = inflater.inflate(R.layout.activity_left, container, false); Handler_Inject.injectView(this, rootView); return rootView; } 只需要在onCreateView裡面調用Handler_Inject.injectView(this, rootView); 即可 在fragment中除了activity的生命周期注解和@InjectLayer注解無法使用外,組件綁定和事件綁定都可以使用,@InjectBefore也可以使用 @InjectBefore 是在組件初始化之前調用
這個是圖片框架重寫了好多次了,總是有點問題,裡面基本上每一段代碼都有注釋,還有一些bug, 因為項目中用的還是這次重寫之前的。 如果大家發現問題,記得告訴我框架中調用的方法名和參數基本上都不會變,避免替換jar導致需要改動大部分代碼。
整個圖片下載的邏輯是這樣的:
具體的流程 可以參考源碼
第一層是LruCache(原理去百度) 第二層是LinkedHashMap 第三層是 view標記 1 當LruCache中的圖片超過了規定了內存,那麼從LruCache移除一個使用最少的,放到LinkedHashMap中 2 當每一張圖片的url對應一個count,一旦加載一張圖片,那麼這個url的count加1 3 自定義AsyImageView繼承ImageView,重寫了onDetachedFromWindow方法,一旦 AsyImageView從當前視圖移除掉會調用onDetachedFromWindow該方法,此刻該圖片所對應的url數目count減1 4 因為listview中的imageview如果用了ViewHolder那麼第3條就不適合了,此刻每一個imagview的hashCode對應一個url, 一旦imagview更換了一個新的url,那麼該imagview的hashcode上一個的引用將被移除, 那麼上一次顯示的url所對應的count將減1 5 當LinkedHashMap超過了規定限制的時候,那麼遍歷所有的count一旦count為0 則移除回收
一:必須條件
必須在配置文件中添加配置,來打開圖片下載引擎的初始化,為了減少啟動時間,默認關閉。 #開啟框架內置的圖片下載 如果不設置 則無法使用框架類的圖片下載 imageload_open=true 二:使用方法
ImageDownloader.download("網絡和本地圖片鏈接",mAsyImageView);
如果需要配置bitmap的高寬
第一種方式:
在xml布局文件中對AsyImageView的高寬進行設置
第二種方式:
全局圖片配置,所有圖片顯示默認用此配置
GlobalConfig globalConfig = GlobalConfig.getInstance(); globalConfig.setMaxWidth(w);
來設置
第三種
SingleConfig config = new SingleConfig(); config ....設置寬高 ImageDownloader.download("網絡和本地圖片鏈接",mAsyImageView,config )
其中優先級
其中GlobalConfig 支持的設置有高寬的設置,內存緩存的大小,默認圖片, 下載失敗的圖片,最大緩存數目,線程池,緩存類型,顯示控制,listview得滑動監聽,圖片加載動畫 其中SingleConfig 支持的設置有高寬的設置,默認圖片,下載失敗的圖片,下載進度,顯示控制,加載動畫
其中SingleConfig 優先於GlobalConfig
mAsyImageView.setTemplate("one"); ImageDownloader.download("url",mAsyImageView);
其中one在配置文件裡面配置,這樣 不管在任何地方,只要AsyImageView.setTemplate(“one”);就可以使用名稱為one的配置了。
支持本地文件加載調用接口不變。
需要進度顯示的:
SingleConfig config = new SingleConfig(); config.setDisplayer(new DisplayerLister() { @Override public void startLoader(AsyImageView imageView) { super.startLoader(imageView); } @Override public Bitmap finishLoader(Bitmap bitmap, AsyImageView imageView) { pin_progress_1.setVisibility(View.GONE); return bitmap; } @Override public void progressLoader(int progress, AsyImageView imageView) { pin_progress_1.setProgress(progress); super.progressLoader(progress, imageView); } }); ImageDownloader.download("url",photo,config);
其中url的服務器必須支持獲取文件長度
需要顯示動畫的:如果是單獨某一個圖片
SingleConfig config = new SingleConfig(); config.setDisplayerAnimation(new FadeInAnimation());
如果是全局的
GlobalConfig config = new GlobalConfig(); config.setDisplayerAnimation(new FadeInAnimation());
其中FadeInAnimation是框架自帶的一個漸變的動畫如果需要自定義 實現DisplayerAnimation接口即可
只要在listview的注解@InjectView(isasy=true)中添加了isasy=true(默認為false) 那麼系統會自動給你注入OnScrollListener滾動事件,以便實現圖片飛行停止才加載,緩慢拖動加載的功能。如果你要實現自己的OnScrollListener
如下
@InjectBefore void test(){ //@InjectView(isasy=true)表示這個listview裡面有網絡圖片下載,並且需要實現滑動停止才加載的功能 //@InjectView(isasy=true)框架會給listview自動注入OnScrollListener,如果你自己也要滾動監聽 //那麼請在此配置,如下 GlobalConfig config = GlobalConfig.getInstance(); config.setOnScrollLoaderListener(new MyOnScrollListener()); System.out.println("before"); } //必須繼承框架內的滾動監聽 class MyOnScrollListener extends OnScrollLoaderListener{ @Override public void onScrollListener(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { ApplicationBean.logger.s("滾動監聽:"+firstVisibleItem); } @Override public void onScrollStateChange(AbsListView view, int scrollState) { ApplicationBean.logger.s("滾動狀態"); } }
@InjectBefore 表示在組件初始化以前開始調用,因為滾動監聽必須在listview被初始化之前賦值,否則無效 將默認使用框架內的滾動監聽
ImageDownloader.download("url", new LoaderLister() { @Override public void finishLoader(String url, File file) { System.out.println("下載完成"+file.getPath()); } @Override public void failLoader(String url) { System.out.println("下載失敗"); } });
如果需要下載進度
ImageDownloader.download("url", new LoaderLister() { @Override public void startLoader(String url) { System.out.println("開始下載"); super.startLoader(url); } @Override public void finishLoader(String url, File file) { System.out.println("下載完成"+file.getPath()); } @Override public void progressLoader(int progress) { System.out.println("下載進度"+progress); super.progressLoader(progress); } });
本文列舉了常用的 Android 開發者選項,了解和熟練使用這些開發者選項,能夠幫助我們定位開發中遇到的問題,輔助我們了解應用的性能問題,對提升開發和優化效率大有
本篇文章小編為大家介紹,Android 網絡圖片查看顯示的實現方法,需要的朋友參考下。 我們的應用或多或少都會從網絡獲取圖片數據然後進行顯示,下面就將實現一個這樣
最近 Google 正式發布了 Android M,並命名為“棉花糖”(Marshmallow),對於開發者來說,有哪些新的技術和變化呢?本文嘗試總結一下 And
Android在執行一些後台操作的時候,比如加載游戲,播放歌曲時,用戶根本不知道程序執行的進度情況,這時候,可以使用進度條來顯示這些進度。 Andorid系統提供