Android知识点
開發tip
- 用getApplication()來取Context當參數 對于需要使用Context對象作為參數的函數,要使用getApplication()獲取Context對象當參數,而不要使用this,除非你需要特定的組件實例!getApplication()返回的Context是屬于Application的,它會在整個應用的生命周期內存在,遠大于某個組件的生命周期,所以即使某個引用長期持有Context對象也不會引發內存泄露。比如toast
- 或許我們較為習慣 if(object == null); 這種寫法,對于直接對象的判斷自然是沒有問題的。但是如果遇到對象嵌套,譬如 if(object.child == null) 的情況,如果一開始 object 就是個 null 對象,可想而知程序在執行條件語句判斷時就會報 NullPointerException 異常。當然你可以先判斷 object 再判斷 child,但與其這樣不如一開始就習慣 if(null == object.child); 來得更方便些,equals() 同理。
- 頻繁操作的文件建議考慮使用緩沖提高程序性能,intent不要傳遞大量數據,使用持久化數據來處理(存在文件中),不要在application中緩存數據
- 在涉及網絡的操作中,必須要考慮到沒有網絡和信號差等情況
- 一些華為機器log和Toast打印一直異常,不要在這上面耽誤時間
- 代碼至少每天備份一次,或者是完善一個功能就備份一次,不要堆積之后一次性備份,因為在你的代碼出問題需要回溯代碼時你需要從服務器上重新取代碼,同時也可以避免代碼不是最新導致最后和其他人合并時不知道改了哪些地方
- 注意:有些開發者可能也發現了,如果我們需要一個圓形的ImageButton的話,其實,我們沒有必要自己寫。如果ImageButton的圖標是固定不變的,我們完全可以讓設計師給我設計一個圓形的圖片,然后直接設置再ImageButton上就可以了。
- 同步方法:SDK里大部分方法都為同步方法,即這個方法執行完畢,才會走后面的代碼。異步方法:帶有callback以及api注釋里明確寫明異步方法的方法,即不需要等這個方法走完,后邊的代碼就已經在執行了,通過callback得到方法執行的結果。
- 不少比較有經驗的Android程序員可能都遇到過這個情況,就是當你的項目變得越來越大,有的時候加載一張drawable-hdpi下的圖片,程序就直接OOM崩掉了,但如果將這張圖放到drawable-xhdpi或drawable-xxhdpi下就不會崩掉,其實就是這個道理。那么經過上面一系列的分析,答案自然也就出來了,圖片資源應該盡量放在高密度文件夾下,這樣可以節省圖片的內存開支,而UI在設計圖片的時候也應該盡量面向高密度屏幕的設備來進行設計。就目前來講,最佳放置圖片資源的文件夾就是drawable-xxhdpi。那么有的朋友可能會問了,不是還有更高密度的drawable-xxxhdpi嗎?干嗎不放在這里?這是因為,市面上480dpi到640dpi的設備實在是太少了,如果針對這種級別的屏幕密度來設計圖片,圖片在不縮放的情況下本身就已經很大了,基本也起不到節省內存開支的作用了。
- 不能在?Activity?沒有完全顯示時顯示PopupWindow和Dialog。例如在activity的onCreate方法里面調用popupwindow的show方法,有可能由于activity沒有完全初始化導致程序異常(android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid),如果非要在一進activity就顯示popupwindow,用handler.post、View.postDelay來處理
- 所有的圖片務必先用http://tinypng.com壓一遍用
- JPG 代替 PNG,由于 JPG 沒有 Alpha 通道,所以文件更小,適用于不需要透明度的圖片可以考慮。
- 不同Module的資源文件、布局名不要相同
- 需要管理相互獨立的并且隸屬于Activity的Fragment使用FragmentManager(),而在Fragment中動態的添加Fragment要使用getChildFragmetManager()來管理,而不是getFragmentManager。
- 在ScrollView中添加一個Android:fillViewport="true"屬性就可以了。顧名思義,這個屬性允許 ScrollView中的組件去充滿它。 當ScrollView沒有fillViewport=“true”時, 里面的元素(比如LinearLayout)會按照wrap_content來計算(不論它是否設了"fill_parent")
- gson同一字段,數據類型不同的字段,類型可以寫object
- radiobutton布局下面倆個button切換時,fragment里有listview會頂到下面,可以在布局初始化完后lv.setFocusable(false)
- 有一種情況是手機并不在我們身邊,我們也無法使用調試工具。此時可以接入一些第三方的日志記錄工具。在開發狀態下不建議使用友盟 360之類sdk,因為很有可能我們的app根本無法連接到網絡就崩潰了。 可以選擇把日志存到本地文件中。再由使用手機的人發回來。一般這個人是測試。如果app未接入任何日志保存工具,可以在data/anr/目錄下查看到所有的ANR異常信息。但需要su權限。否則無法訪問到。
- 在復雜的布局上,比如很多app的首頁需要加載不同類型的item。使用了RecyclerView多類型加載,刷新數據時一定要使用單獨對item刷新api。切勿使用notifyDataSetChanged()方法,這里要用兩個參數的notifyItemChanged(1,"gfg")方法。
- 當無法通過搜索解決問題的時候,讀源碼是最快的解決思路。千萬不要瞎猜和嘗試隨緣寫代碼來解決問題。
- .9圖的左上代表可以拉伸的區域,右下代表可以填充的區域
- 多語言字符串設置要都配置上,要不然就報android.content.res.Resources$NotFoundException
- 在8.0上切換語言部分文字沒有切換,原因是getResources原來是通過application的,改成activity的就可以了
- 找不到問題,可以二分注釋代碼來定位問題
- TextView.setTextColor方法不能用R.Color.XXX設置顏色
UI問題
一段文字顏色不同點擊不同,不想寫多個textview,可以這樣寫
String html="僅限<font color=#FF9900>"+offer.getCardGroupName()+"</font>使用"; nrbankTextView.setText(Html.fromHtml(html));也可以這樣寫
String content = "發現" + newGroup.size() + "張新卡片"; int textColor = getResources().getColor(R.color.import_card_red); SpannableString spannableString = TextStyleUtils.setTextStyle(content, newGroup.size() + "張", textColor); tv_.setText(spannableString);也可以這樣寫:
private void setCurrentTip() {StringBuilder actionText = new StringBuilder();actionText.append("<a style=\"text-decoration:none;\" href='text' >若平臺今日快速還款額度用完,還款將于次日到賬\n</a>");actionText.append("<a style=\"text-decoration:none;\" href='text' >查看</a>");actionText.append("<a style=\"text-decoration:none;\" href='blue' >規則</a>");tvBankArrivaldesc.setText(Html.fromHtml(actionText.toString()));tvBankArrivaldesc.setMovementMethod(LinkMovementMethod.getInstance());CharSequence text = tvBankArrivaldesc.getText();int ends = text.length();Spannable spannable = (Spannable) tvBankArrivaldesc.getText();URLSpan[] urlspan = spannable.getSpans(0, ends, URLSpan.class);SpannableStringBuilder stylesBuilder = new SpannableStringBuilder(text);stylesBuilder.clearSpans();for (URLSpan url : urlspan) {FeedTextViewURLSpan myURLSpan = new FeedTextViewURLSpan(url.getURL(), getActivity());stylesBuilder.setSpan(myURLSpan, spannable.getSpanStart(url),spannable.getSpanEnd(url), spannable.SPAN_EXCLUSIVE_EXCLUSIVE);}tvBankArrivaldesc.setText(stylesBuilder);}static class FeedTextViewURLSpan extends ClickableSpan {private String clickString;private Context context;public FeedTextViewURLSpan(String clickString, Context context) {this.clickString = clickString;this.context = context;}@Overridepublic void updateDrawState(TextPaint ds) {ds.setUnderlineText(false);//去掉下劃線//給標記的部分 的文字 添加顏色if (clickString.equals("blue")) {ds.setColor(Color.parseColor("#4D8FDD"));} else if (clickString.equals("text")) {ds.setColor(Color.parseColor("#999999"));}}@Overridepublic void onClick(View widget) {Intent intent = new Intent();// 根據文字的標記 來進行相應的 響應事件if (clickString.equals("blue")) {ToastUtils.show(context, "規則");}}}想每次進入頁面刷新,可以放在onResume方法里(不推薦)
顏色透明度:#7f000000 代表50%透明度的黑色
ImageView的android:adjustViewBounds屬性
http://blog.csdn.net/pingchuanyang/article/details/9252689
framelayout兩布局重疊,如何讓下層不響應事件
在layout文件里本層下增加Android:clickable="true"
在上層布局的父布局上增加android:clickable="true"
給圖片設置背景,例如ui給的圖背景透明的圖片
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item><shape><solid android:color="#1c69ac" /><corners android:radius="5dp"/></shape></item><itemandroid:left="15dp"android:right="15dp"android:top="15dp"android:bottom="15dp"android:drawable="@drawable/icon_yingwen_fuhao_keyboard_del_default"/> </layer-list>由于listview的復用機制,當給一個控制設置狀態的時候,相應的要給其他控件也設置狀態(else),否則就會復用
?listview如果單獨更新某個控件的時候,可以更改單個數據的狀態,然后notify
viewpager+fragment
//界面可見時再加載數據@Overridepublic void setUserVisibleHint(boolean isVisibleToUser{super.setUserVisibleHint(isVisibleToUser);if (isVisibleToUser) {mMyWalletPresenter.reqRanking(position);//[2周排行,1總排行]}}CardView
使用android:background設置背景顏色無效。 app:cardBackgroundColor 設置背景顏色
NestedScrollView嵌套RecyclerView滑動卡頓解決方案
如果你APP的API適配的minSdkVersion高于21,直接在RecyclerView中加上android:nestedScrollingEnabled="false"或者禁用recycleview滑動
selector異常
Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #3: <item> tag requires a 'drawable' attribute or child tag defining a drawable
產生原因:我的一個button按鈕的background屬性中設置成"@color/button_text_selector",按照異常來說,這個background這個屬性的值必須是drawable類型的,不能是color類型。
代碼寫陰影
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"><!-- 陰影部分 --><!-- 個人覺得更形象的表達:top代表下邊的陰影高度,left代表右邊的陰影寬度。其實也就是相對應的offset,solid中的顏色是陰影的顏色,也可以設置角度等等 --><itemandroid:bottom="2dp"android:left="2dp"android:right="2dp"android:top="2dp"><shape android:shape="rectangle"><gradientandroid:angle="270"android:endColor="#0F000000"android:startColor="#0F000000" /><cornersandroid:bottomLeftRadius="6dip"android:bottomRightRadius="6dip"android:topLeftRadius="6dip"android:topRightRadius="6dip" /></shape></item><!-- 背景部分 --><!-- 形象的表達:bottom代表背景部分在上邊緣超出陰影的高度,right代表背景部分在左邊超出陰影的寬度(相對應的offset) --><itemandroid:bottom="5dp"android:left="3dp"android:right="3dp"android:top="3dp"><shape android:shape="rectangle"><gradientandroid:angle="270"android:endColor="#FFFFFF"android:startColor="#FFFFFF" /><cornersandroid:bottomLeftRadius="6dip"android:bottomRightRadius="6dip"android:topLeftRadius="6dip"android:topRightRadius="6dip" /></shape></item> </layer-list>單選
public void setClicked(int clicked) {mapClassfiyAdapter.setClicked(clicked);}public void setClicked(int clicked){this.clicked=clicked;notifyDataSetChanged();}if(i==clicked){ tv_classfiy.setTextColor(mContext.getResources().getColor(R.color.map_pop_click));} else {tv_classfiy.setTextColor(mContext.getResources().getColor(R.color.white));}多選
// 用來控制CheckBox的選中狀況private static HashMap<Integer, Boolean> isSelected;public MapClassfiyAdapter(Context mContext, List<String> classfiyList) {this.mContext = mContext;isSelected = new HashMap<Integer, Boolean>();}// 初始化isSelected的數據private void initDate() {for (int i = 0; i < classfiyList.size(); i++) {getIsSelected().put(i, false);}}public HashMap<Integer, Boolean> getIsSelected() {return isSelected;}public void setIsSelected(HashMap<Integer, Boolean> isSelected) {MapClassfiyAdapter.isSelected = isSelected;}@Overridepublic View getView(int i, View convertView, ViewGroup viewGroup) {...if(getIsSelected().get(i)){tv_classfiy.setTextColor(mContext.getResources().getColor(R.color.map_pop_click));}else{tv_classfiy.setTextColor(mContext.getResources().getColor(R.color.white));}tv_classfiy.setText(classfiyList.get(i));}---public void setClicked(int clicked) {isSelected = mapClassfiyAdapter.getIsSelected();Boolean aBoolean = isSelected.get(clicked);if(aBoolean){isSelected.put(clicked,false);}else{isSelected.put(clicked,true);}mapClassfiyAdapter.setIsSelected(isSelected);}描邊
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:left="-2dp"android:right="-2dp"><shape><solid android:color="@color/white" /><strokeandroid:width="1.5dp"android:color="#80ffffff" /></shape></item></layer-list>---<layer-listxmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:right="-2dp"//負數,不描右邊><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solidandroid:color="#EFEFEF"/><cornersandroid:topLeftRadius="10dp"android:topRightRadius="0dp"android:bottomRightRadius="0dp"android:bottomLeftRadius="10dp"/><strokeandroid:width="0.5px"android:color="#505050"/></shape></item> </layer-list>popWindow點背景消失
mPopupWindow = new PopupWindow(mPopupView,ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);//產生背景變暗效果,布局背景要改// 根布局背景android:background="#00ffffff"backgroundAlpha(0.5f);mPopupWindow.setOutsideTouchable(true);mPopupWindow.setFocusable(true);mPopupWindow.setBackgroundDrawable(new BitmapDrawable());mPopupWindow.setOnDismissListener(new PoponDismissListener());mMyHandler.postDelayed(new Runnable() {@Overridepublic void run() {mPopupWindow.showAtLocation(mPopupView, Gravity.CENTER, 0, 0);}}, 200);...class PoponDismissListener implements PopupWindow.OnDismissListener {@Overridepublic void onDismiss() {backgroundAlpha(1f);}}private void backgroundAlpha(float v) {WindowManager.LayoutParams lp = context.getWindow().getAttributes();lp.alpha = v; //0.0-1.0context.getWindow().setAttributes(lp);}數據庫升級
新增版本號,然后
數字后加2個點
DecimalFormat df = new DecimalFormat("########0.00"); crt_pp_money.setText("¥" + df.format(Double.valueOf(money)));填充字符串
<string name="crt_shift_limit">銀行單筆限額%1$d萬,單日限額號%2$d萬</string> bankMessage.setText(getResources().getString(R.string.crt_shift_limit,3,5));其他問題
webview post
webView.postUrl(mUrl,postdata.getBytes());
webview重定向引起的問題
解決方法:
或者
@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);mIsPageLoading= false;//重定向是不回執行finished方法的}public void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);mIsPageLoading= true;}webview:顯示404等異常狀態都有回調,可以顯示一個友好的界面
可以通過URL是否包含某個字段判斷去哪個頁面
try-catch 捕獲異常可以捕獲里return出去
手機適配
String PhoneName = String.valueOf(android.os.Build.MANUFACTURER);if (PhoneName.equals("OPPO")) {AutoLogin1.setVisibility(View.INVISIBLE);AutoLogin2.setVisibility(View.INVISIBLE);}華為等虛擬鍵盤遮擋問題
//因為某些機型是虛擬按鍵的,所以要加上以下設置防止擋住按鍵.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);如果你觸發了一個intent,而且沒有任何一個app會去接收這個intent,那么你的app會crash。為了驗證是否有合適的activity會響應這個intent,需要執行queryIntentActivities() 來獲取到能夠接收這個intent的所有activity的list。如果返回的List非空,那么你才可以安全的使用這個intent。例如:
PackageManager packageManager = getPackageManager();List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);boolean isIntentSafe = activities.size() > 0;if (isIntentSafe) {startActivity(mapIntent);}檢查是否有某個權限
public static boolean hasPermissions(Context context, String... perms) {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {return true;}for (String perm : perms) {//PERMISSION_DENIEDboolean hasPerm = (ContextCompat.checkSelfPermission(context, perm) ==PackageManager.PERMISSION_GRANTED);if (!hasPerm) {return false;}}return true;}boolean location = hasPermissions(this, Manifest.permission.ACCESS_COARSE_LOCATION);跳轉到別的APP
private void doStartApplicationWithPackageName(String packagename) {Intent intent = new Intent();PackageInfo packageinfo = null;PackageManager packageManager = context.getPackageManager();try {packageinfo = packageManager.getPackageInfo(packagename, 0);} catch (PackageManager.NameNotFoundException e) {e.printStackTrace();}if (packageinfo == null) {intent.setClass(context, NoLianshuaActivity.class);context.startActivity(intent);dismiss();return;}intent = new Intent(Intent.ACTION_VIEW,Uri.parse("mydemo://go?money=" + money + "&isFromMydemo=" + true));} <activity android:name=".Main2Activity"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="mydemo" /></intent-filter> </activity>另一個APP
private void parseIntentUrl() {Intent intent = getIntent();String action = intent.getAction();if (Intent.ACTION_VIEW.equals(action)) {Uri uri = intent.getData();if (uri != null) {String host = uri.getHost();String dataString = intent.getDataString();String id = uri.getQueryParameter("goodsId");String path = uri.getPath();String path1 = uri.getEncodedPath();String queryString = uri.getQuery();Log.d("Alex", "host:"+host);Log.d("Alex", "dataString:" + dataString);Log.d("Alex", "id:" + id);Log.d("Alex", "path:" + path);Log.d("Alex", "path1:" + path1);Log.d("Alex", "queryString:" + queryString);}}}這樣寫bean的字段,字段是new_p也能解析
@SerializedName("new_p")
private String psw;
ViewPager越界
ViewPager的子控件個數(getChildCount())最多為3(在destroyItem()中調用了removeView()),如果要獲取ViewPager某個子頁面,千萬不能使用getChildAt(position),會造成數組越界。可以通過這樣來獲取。
轉載于:https://www.cnblogs.com/sixrain/p/9720295.html
總結
以上是生活随笔為你收集整理的Android知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信卡券 - 微信公众平台 整理笔记
- 下一篇: android sina oauth2.