這裏是做者(OCN.Yang)在Android初級階段遇到的那些坑坑窪窪,有些仍是開發中要知道的小技巧。相信大多數初學者不免也會遇到相同的坑,你們大概看看有者避之,還沒遇到的就躲之。大牛和已經進階的朋友能夠繞道(相信大家很忙的)。java
這篇博客首發在個人我的博客網站 www.ocnyang.comandroid
原文地址git
查看代碼的大綱 即類的方法列表。正則表達式
能夠給背景設置一個null值,在必定狀況下這樣作是有必要的。apache
TextUtils.isEmpty(String str)
複製代碼
當LinearLayout佈局中設置**orientation="vertical"**屬性:數組
設置爲單實例模式(singleInstance)的Activity,會單獨開一個任務棧單獨存放這個activity,這個任務棧只會在程序退出後消除。緩存
Intent intent = new Intent();
/* 開啓Pictures畫面Type設定爲image */
intent.setType("image/*");
/* 使用Intent.ACTION_GET_CONTENT這個Action */
intent.setAction(Intent.ACTION_GET_CONTENT);
/* 取得相片後返回本畫面 */
startActivityForResult(intent, 1);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
ContentResolver cr = this.getContentResolver();
try {
Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
ImageView imageView = (ImageView) findViewById(R.id.iv01);
/* 將Bitmap設定到ImageView */
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
Log.e("Exception", e.getMessage(),e);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
複製代碼
主要方法:網絡
R文件的編譯原理:當資源文件或id命名中其中一個文件的命名不知足規範時,R文件總體就不會再編譯。app
android:descendantFocusability="blocksDescendants"//阻止後代得到焦點
複製代碼
getResources().getStringArray(R.array.city)
複製代碼
Java代碼ide
System.out.println(":ab:cd:ef::".split(":").length);//末尾分隔符所有忽略
System.out.println(":ab:cd:ef::".split(":",-1).length);//不忽略任何一個分隔符
System.out.println(StringUtils.split(":ab:cd:ef::",":").length);//最前面的和末尾的分隔符所有都忽略,apache commons
System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一個分隔符 apache commons
輸出:
4
6
3
6
複製代碼
看了下jdk裏String類的**public String[] split(String regex,int limit)**方法,感受平時不太會用這方法,覺得在用正則表達式來拆分時候,若是匹配到的字符是最後一個字符時,會拆分出兩個空字符串,
例如"o"split("o",5) or "o"split("o",-2)時候 結果是"" "" 也就是下圖中紅框裏的內容,因此平時通常都用split(String regex) 方法,其實也就等同於split(String regex,0)方法,把結尾的空字符串丟棄!
////xListView上滑刷新,下滑加載更多///swapListView側滑刪除/
只能inflatay一次。否則會報錯。
以圖片的左上角爲座標(0,0),分別計算出pivotX和pivotY的數值:50%是圖片自己大小的一半,50%p是父窗體寬高的一半長度。而後在圖片的左上角的基礎上加上這兩個數組
位移也是一樣的計算方式
ButterKnife Gosn android.selector.generat
android 中的控件的margin 和 padding 都是不會影響控件的設置寬高。(這點和網頁設計是不同的)
當佈局或id報找不到的錯時,可能就是R文件出錯。
自定義ListView中,若是item採用多種類型的佈局。那麼在getItemType中的下標必定要從0開始。否則會報下標越界異常。
public static void main(String[] args) {
String str = "<div><h3 ..>dsijiswer*dfhjgf</h3></div><table><h3>sdsd</h3></table>";
Pattern p = Pattern.compile("<h3.*?/h3>");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
}
複製代碼
在drawer文件夾下建立一個shape的圖形文件
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<size android:width="15dp" />
<solid android:color="@android:color/transparent" />
</shape>
複製代碼
在linearLayout裏設置屬性divider爲上圖形,同時設置showdivider屬性
txtZQD = (TextView) findViewById(R.id.txtZQD);
Drawable[] drawable = txtZQD.getCompoundDrawables(); //獲取它先後左右的圖片
// 數組下表0~3,依次是:左上右下
drawable[1].setBounds(100, 0, 200, 200);
txtZQD.setCompoundDrawables(drawable[0], drawable[1], drawable[2],drawable[3]);
複製代碼
在加載佈局的時候要用 View.inflate(context,R.layout.img_share,this);
或者 LayoutInflater.from(context).inflate(R.layout.img_share,this);
不能用 LayoutInflater.from(context).inflate(R.layout.img_share,null);這樣加載不上。
配置錯誤緣由:一、導包有誤。二、少導包。三、重複導包。
Scrollview裏嵌套Gridview,Gridview搶焦點問題(顯示佈局的時候總是先從Gridview的第一個item顯示)
解決方法:在獲取inflate view以後,代碼給GridView.setFocusable(false)就能夠了
這裏的listview的item裏嵌套了橫向滑動的scrollview的gridview,
一樣的問題,一樣的解決方案:在listview的adapter中在加載完item以後對gridview設置setFocusable(false)。 這裏須要注意的是,是在搶焦點的列表的父容器創建以後就對列表設置取消焦點。
例如:
在ListView中嵌套GridView中:
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_listview_home, null);
viewHolder = new ViewHolder(convertView);
viewHolder.mGridIilh.setFocusable(false);
複製代碼
在fragment佈局中存在列表搶佔焦點:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_cheapsale, null);
ButterKnife.inject(this, view);
mGridFragmentCheapsale.setFocusable(false);
複製代碼
在Activity佈局中存在列表搶佔焦點:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sale);
ButterKnife.inject(this);
mListviewHome.setFocusable(false);
複製代碼
在gridview和listview初始化數據時自動調用或者咱們顯示調用notifyDataSetChanged的時候第一個item會被選中並會搶焦點。
android4.4在調用notifyDataSetChanged的時候註釋掉了判斷touchmode的代碼,致使一調用notifyDataSetChanged就模擬用戶點擊了gridview。
咱們繼承gridview或者listview重寫裏面的isInTouchMode方法:
[java] view plaincopy
/**
* 屏蔽android4.4 setAdapter時View搶焦點的BUG
*/
@Override
public boolean isInTouchMode() {
if(19 == Build.VERSION.SDK_INT){
return !(hasFocus() && !super.isInTouchMode());
}else{
return super.isInTouchMode();
複製代碼
listview默認背景和系統窗口同樣是透明的,若是給listview加上背景圖片,或者背景顏色時,滾動時listview會黑掉,由於滾動時,列表裏面的view重繪用的依舊是系統默認的透明色,顏色值爲#FF191919
解決辦法:
Intent intent = new Intent();
intent.setClassName("com.android.settings","com.android.settings.ManageApplications");
intent.setAction("android.intent.action.MAIN");
try {
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
複製代碼
解決之道:在EditText的父級控件中找一個,設置成
android:focusable="true"
android:focusableInTouchMode="true"
複製代碼
這樣,就把EditText默認的行爲截斷了!
若是RadioGroup中設置默認選中一個RadioButton後,在選擇時會選中兩個的問題
解決方法:
不須要設置RadioButton的默認選中, 這樣會使RadioButton一直處於選中狀態.
咱們應該給RadioGroup設置選中的RadioButton,
也就是說把radioButton.setCheck(true);
更改成radioGroup.check(radioButton.getId());
一、自定義ImageView重寫View的onMeasure方法
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context) {
super(context);
}
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Drawable d = getDrawable();
if(d!=null){
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = MeasureSpec.getSize(widthMeasureSpec);
//高度根據使得圖片的寬度充滿屏幕計算而得
int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
}else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
複製代碼
二、設置ImageView的屬性
//寬度填滿屏幕
android:layout_width=」match_parent」
android:scaleType=」fitXY」
android:layout_height=」wrap_content」
//保持比例,必定要設置
android:adjustViewBounds=」true」
複製代碼
由於Glide加載圖片的規則是根據imageview的大小調整圖片。可是ImageView的大小爲ImageView寬度填滿屏幕,高度自適應的時候,Glide加載的圖片就會顯示不出來,爲此咱們選擇了一種迂迴的方式加載:先請求圖片爲bitmap,這個時候圖片就有必定的尺寸了,再設置到ImageView中就能夠自適應了:
Glide.with(GraphicDetailsFragment.this)
.load((new StringBuffer(Const.URL_HEAD).append(mStringList.get(position))).toString())
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
viewHolder.mImageView.setImageBitmap(resource);
}
});
複製代碼
設置GridView的android:listSelector屬性 android:listSelector="@null" 設置後四周空隙就消除了
1.設置item的行間距:
能夠在xml佈局文件中的listView下設置xml屬性:
android:divider="#00000000"
android:dividerHeight="18dp"
解釋:分隔線透明,高度爲18dp。
2.去掉item之間的分割線:
每一個item之間都有分割線,若是單純想去掉分割線,方法仍是不少的:
3.隱藏頭部分隔線
listview分割線會在頭部、數據item、及根部的底部打印,若是要取消頭部分割線必須 先設置其方法
addHeaderView(headView, null, true);
addFooterView(footView, null, true);
複製代碼
注意:第三個參數必須爲true,不然無效
//顯示頭部出現分割線
listview.setHeaderDividersEnabled(true);
//禁止底部出現分割線
listview.setFooterDividersEnabled(false);
複製代碼
今天android stutio出現
Error:Failed to create directory'C:\Users\Administrator\.gradle\caches\2.8\scripts\ijinit7_5jx13p26aqkoramvuhfn0lqca\init\classes'
這個問題,解決的辦法是:
File
下面有個 Invalidate Caches/Restart
,彈出一個框,點擊 Invalidate and Restart
按鈕,等待重啓就OK了。
TextView.append(CharSequence text);//在現有字符串的基礎上向字符串緩存區追加字符串;(本身想法:可能會在刷新頁面的時候形成屢次重複追加,因此不提倡使用)
複製代碼
疑問:兩個嵌套,fragment給第二個Fragment經過setArguments(bundle)傳值,傳遞不過去。
setScrollbarFadingEnabled(true);
//不活動的時候隱藏,活動的時候顯示
setVerticalScrollBarEnabled(true);
//不活動的時候隱藏,活動的時候也隱藏
複製代碼
android: scrollbars="none"與 setVerticalScrollBarEnabled(true); 效果同樣。
重寫ListView的onMeasure的方法來解決滑動衝突的應用中,ListView是不能設置divider和高度的,若是設置了,最後一個item顯示不全,這是由於onMeasure在根據條目設置ListView的高度時並無把divider的高度設置進去。
Error:Cannot change dependencies of configuration ':app:_debugAnnotationProcessor' after it has been resolved.
當導入一個第三方庫的時候報的錯誤。是由於這個庫依賴的某些庫版本太高而你的Android studio沒有下載這個庫。
ScrollView中沒有match_parent這麼一說,至關於它內部的控件高度是沒有參考物的。match_parent的失效,它會表現成爲wrap_content。
在android中建立菜單menu時須要重寫Activity的onCreateOptionsMenu(Menumenu)方法,這個方法只在第一次建立的時候調用一次,因此若是以後想對menu進行動態的修改,那麼就不能再對onCreateOptionsMenu作什麼手腳,就要用到onPrepareOptionsMenu(Menumenu)方法了。
onPrepareOptionsMenu與onCreateOptionsMenu不一樣的是,他在每次按下menu硬鍵以前會被調用,因此能夠在這裏動態的改變menu。
注意:在onPrepareOptionsMenu(Menumenu)函數中,首先須要調用:
super.onPrepareOptionsMenu(menu);
menu.clear();
複製代碼
若是沒有clear而直接add的話,那麼菜單中菜單項是會「追加」的,這樣隨着你不停的點menu鍵,菜單項就不停的增長。
另外,android系統默認的菜單樣式是支持最多3個一行,若是有4項就每行2個有2行...若是想自定義樣式,可使用xml文件定義樣式。
一個Activity在manifet裏聲明瞭Android:parentActivityName;這時候經過Activity左上角的返回按鈕點擊返回,啓動聲明的父Activity,而且總會先調用父Activity的OnDestroy方法,點擊子Activity的左上角返回按鈕的時候,調用邏輯以下:
MainActivity.onDestroy();
MainActivity.onCreate(null);
MainActivity.onStart();
複製代碼
解決方案是: 爲設置MainActivity屬性android:launchMode=singleTop (這個大概的意思是,消除先調用Destroy方法的解決方案)
順便腦補android:parentActivityName的做用,就是爲了左上角給子Activity加一個返回按鈕,具體信息以下:
Android 4.1 提升性能、加強用戶體驗
App 棧導航:經過設置 android:parentActivityName 改變回退棧的內容,若是棧中沒有 parentActivity,則合成棧,經過 onPrepareNavigateUpTaskStack() 改變 parentActivity 中的內容。
條件編譯(C裏面的概念)是個好東西,可是在java體系中卻沒有這樣的預約義。可是咱們能夠根據java編譯時對代碼的優化機制實現條件編譯。
java在編譯中有這樣一條原則:「編譯器會對代碼進行優化,對於條件永遠爲false的語句,JAVA編譯器將不會對其生成字節碼。」
這樣一來,咱們只須要在Const(靜態變量類)中定義一個isDebug的布爾變量,而後對想要進行條件編譯的代碼用
if(isDebug){
...代碼語句...
}
複製代碼
包含起來。這樣你能夠經過控制isDebug的值實現條件編譯。當isDebug爲false時,if條件內的...代碼語句...會被編譯器忽略,也就是不會生成對應的字節碼。
//實現的原理是 java的反射?
int resId = (Integer) R.drawable.class.getField("icon").get(null);
holder.img.setImageResource(resId);
複製代碼
須要明白的一點就是 每一張圖片的name 都是 R.drawable的一個字段
在Values下建立數組文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--適合白色字體的彩虹色-->
<integer-array name="itemcolor">
<item>0xFF79429D</item>
<item>0xFF5691F5</item>
<item>0xFF76BA55</item>
<item>0xFFB3E0E0</item>
<item>0xFF27C9C2</item>
<item>0xFF92AD6B</item>
<item>0xFFEC4F4F</item>
<item>0xFFEE6593</item>
<item>0xFFFFAC5A</item>
<item>0xFF6296AF</item>
<item>0xFFBF8A28</item>
<item>0xFF319388</item>
</integer-array>
</resources>
複製代碼
這裏須要注意的是顏色的數值必須是8位,即前兩位的透明位不能省略。 而後就能夠獲取
Resources resources = context.getResources();
mColorArray = resources.getIntArray(R.array.itemcolor);
...
setBackgroundColor(R.id...., mColorArray[Position % mColorArry.length]);
複製代碼
有時候 ScrollView 嵌套 LinearLayout 時會有顯示不全的狀況,這個時候應該看看 ScrollView 的父佈局是否是用的 CoordinatorLayout。
當外部用 CoordinatorLayout 時,內部應該用 NestedScrollView ,否則會產生不肯定的 bug。
一樣在 CoordinatorLayout 內部使用 ViewPager & TabLayout 來顯示不一樣的 Fragment 時,若是 Fragment 內使用 ScrollView 也會有顯示不全的狀況。
double sin20 = Math.sin(Math.PI * 20 / 180); //0.3420201433256687 double sin201 = Math.sin(20 / 180 * Math.PI); //0.0
找到緣由了,當先計算20/180的時候是按int類型運算的,獲得的結果是0。因此最後結果爲0.
Android4.0 以上 AlertDialog 在觸摸對話框邊緣外部,對話框消失
能夠設置這麼一條屬性,固然必須先AlertDialog.Builder.create()以後才能調用這兩個方法
方法一:
setCanceledOnTouchOutside(false);
調用這個方法時,按對話框之外的地方不起做用。按返回鍵還起做用
方法二:
setCancelable(false);
調用這個方法時,按對話框之外的地方不起做用。按返回鍵也不起做用
當你的項目中用到用 Vector 圖形時,請注意事項能夠參考www.jianshu.com/p/e3614e7ab…
另外值得注意的是
//mDrawableActive = ContextCompat.getDrawable(context, R.drawable.vec_checkbox_fill_circle_outline);
//mDrawable = ContextCompat.getDrawable(context, R.drawable.vec_checkbox_blank_circle_outline);
//解決 vector 「資源未找到」 錯誤,能夠考慮用一下方法代替
try {
mDrawableActive = AppCompatDrawableManager.get()
.getDrawable(context, R.drawable.vec_checkbox_fill_circle_outline);
mDrawable = AppCompatDrawableManager.get()
.getDrawable(context, R.drawable.vec_checkbox_blank_circle_outline);
} catch (Resources.NotFoundException notFoundException) {
Logger.e(notFoundException.getMessage());
} catch (Exception e) {
Logger.e(e.getMessage());
} finally {
mDrawableActive = context.getResources().getDrawable(R.drawable.vec_checkbox_fill_circle);
mDrawable = context.getResources().getDrawable(R.drawable.vec_checkbox_empty_circle);
}
複製代碼
同時須要注意的是:使用Vector時好像不能關閉硬件加速:
android:hardwareAccelerated="false"//不要在配置文件中使用這個設置
複製代碼
當你在測試應用時,若是在部分機型上運行正常,而在部分機型上出現 OOM ,除了對應用再次作各類優化外,你能夠在配置文件中加上:
<application
...
android:largeHeap="true"
...
/>
複製代碼
說不定就行了呢。
引發緣由:
在V7包下,Wiget.AppCompat.Toolbar的parent中,contentInsetStart(默認的有值)這個屬性就是引發自定義ActionBar不能徹底填充的緣由。
<style name="ClubToolbar" parent="Widget.AppCompat.Toolbar">
<item name="contentInsetStart">0dp</item><!-- 設置該屬性解決空白部分-->
</style>
複製代碼
而後在AppStyle中(必定在這,單獨在Toolbar的style中設置不起做用)重寫Toolbar的屬性:
<item name="toolbarStyle">@style/ClubToolbar</item>
複製代碼
DrawerLayout.setDrawerListener(new ActionBarDrawerToggle);//有動畫效果的菜單圖標
DrawerLayout.setScrimColor(Color.TRANSPARENT) //去除側滑時的陰影遮罩效果
在必定版本中的NavigationView的都是有半透明效果的
若是不須要能夠經過設置下面屬性去除:
app:insetForeground="@android:color/transparent"
複製代碼
同時若是想要Nav在使用中沒有背景全透明直接設置背景爲#00000000;同時去除 headerLayout 的背景便可。
使用 SDK:15~25 測試版本:Android 6.0;Android 4.3(在這兩個版本上都存在,中間版本必定也存在)
<!--這裏只給父佈局 LinearLayout 設置的點擊事件,其餘控件沒有設置任何監聽事件-->
<LinearLayout
android:id="@+id/linearlayout"
android:layout_width="match_parent"
android:layout_height="35dp"
android:orientation="horizontal">
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Time"/>
<TextView
android:id="@+id/time_value"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="date"/>
</LinearLayout>
複製代碼
一次無心中發現的。若是給 TextView 設置一個 inputType 屬性,按理說,inputType 應該是不起做用的,可是這裏將會存在一個神奇的事情(不知道算不算一個原生bug):
android:overScrollMode="never"
複製代碼
android:inputType="textMultiLine" //能夠顯示多行
android:gravity="left|top" //輸入時光標左上角
android:minLines="6" //最小顯示6行
複製代碼
左邊和上邊的黑邊表示拉伸區域。右邊和下邊的黑邊表示填充區域
其實,NavigationView是一個RecyclerView(在23.1.0版本以前是ListView),header佈局一般是0號元素。在Support Library v23.1.1版本中,可使用以下方法很方便地獲取到header中的view:
View headerLayout = navigationView.getHeaderView(0); // 0-index header
複製代碼
而在23.1.0版本中,就須要經過這種方法:
View headerLayout =
navigationView.inflateHeaderView(R.layout.navigation_header);
panel = headerLayout.findViewById(R.id.viewId);
// panel won't be null
複製代碼
限制只輸入某些值包括數字、字母等
android:digits="0123456789abcdefghigklmnopqrstuvwxyz"
複製代碼
上面這行代碼能夠是你任何的限制,只能輸入什麼就到裏面寫就能夠了,上面寫的是隻能夠輸入數字和字母。
android:inputType="textPassword"
android:digits="0123456789abcdefghigklmnopqrstuvwxyz"
複製代碼
這裏是只能輸入數字和字母而且是密碼格式,這兩個設置並無衝突, android:inputType="textPassword"
這裏是文本,是能夠輸入中文的,可是要是你加了 android:digits="0123456789abcdefghigklmnopqrstuvwxyz"
,inputType 這裏的中文就會失效了,可是 password 不會失效,這裏只是打個比方,你們都懂的。
inputType的屬性值
android:inputType="none"
android:inputType="text"
android:inputType="textCapCharacters" 字母大寫
android:inputType="textCapWords" 首字母大寫
android:inputType="textCapSentences" 僅第一個字母大寫
android:inputType="textAutoCorrect" 自動完成
android:inputType="textAutoComplete" 自動完成
android:inputType="textMultiLine" 多行輸入
android:inputType="textImeMultiLine" 輸入法多行(若是支持)
android:inputType="textNoSuggestions" 不提示
android:inputType="textUri" 網址
android:inputType="textEmailAddress" 電子郵件地址
android:inputType="textEmailSubject" 郵件主題
android:inputType="textShortMessage" 短訊
android:inputType="textLongMessage" 長信息
android:inputType="textPersonName" 人名
android:inputType="textPostalAddress" 地址
android:inputType="textPassword" 密碼
android:inputType="textVisiblePassword" 可見密碼
android:inputType="textWebEditText" 做爲網頁表單的文本
android:inputType="textFilter" 文本篩選過濾
android:inputType="textPhonetic" 拼音輸入 //數值類型
android:inputType="number" 數字
android:inputType="numberSigned" 帶符號數字格式
android:inputType="numberDecimal" 帶小數點的浮點格式
android:inputType="phone" 撥號鍵盤
android:inputType="datetime" 時間日期
android:inputType="date" 日期鍵盤
android:inputType="time" 時間鍵盤
複製代碼
問題描述:
開發中,遇到退出登陸時,須要將界面跳轉到登陸界面,並將棧中全部Activity清空。
解決辦法
Intent intent = new Intent(A.this,B.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
複製代碼
startActivity 的時候傳遞 FLAG_ACTIVITY_CLEAR_TASK
這個標誌,那麼這個標誌將會清除以前全部已經打開的 activity
.而後將會變成另一個空棧的 root ,而後其餘的 Activitys 就都被關閉了.這個方法必須跟着 {@link #FLAG_ACTIVITY_NEW_TASK}
一塊兒使用.
inflate(int resource, ViewGroup root, boolean attachToRoot)
複製代碼
大大小小的坑,無處不在,防不勝防。後續會繼續更新這篇博文的。
本博客是做者(OCN.Yang)原創
轉載請標明原地址:ocnyang.com/2016/08/31/…