汪建军的博客

休迅飞凫,飘忽若神,凌波微步,罗袜生尘。

Android developer, sometimes thinking, sometimes try it.


Android开发路上的踩坑锦集(三)

(三)会有一些想问题的方法。


1、给Listview设置高度:android:minHeight="50dp"

2、android studio的assets包是在main下面和“java”包同一层的

3、so库加载gif例子:
lib里的两个文件夹是自动生成的,里面两个so文件可以直接用(有lib的两个文件夹里有两个so文件就可以删掉整个jni包,删后记得取消掉构建器)
在android studio里放到了main下面和“java”包同一层,名叫“jniLibs”

Android.mk内容:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := prebuilt/armeabi/libgif.so /**预编译so库,在jni包下*/  
LOCAL_MODULE    := gif /**名字随意,不是构建器的名字*/

include $(PREBUILT_SHARED_LIBRARY)  

Android.mk内容:

APP_PROJECT_PATH := $(call my-dir)  
APP_PLATFORM :=android-9  
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/Android.mk  
APP_ABI := armeabi armeabi-v7a  

新建构建器,配置ndk位置等,把构建器上移到最上,编译后会自动在lib生成两个文件夹

4、fastjson用parseObject能解析任何多字段少字段,不能使用parseArray,标准例子:
BaseResponse baseResponse = JSON.parseObject(s, BaseResponse.class);
解析的类只能是自己的内部类或者单独类,不能是其他类的内部类。

5、直接搜问题或者错误原句,往往能从侧面得到答案

6、系统下载器指定目录和文件名(无需判断目录是否存在,目录名大小写无所谓,也不用写绝对路径,默认在SD卡下):
String downloadName = recommend.getName()+".apk";
request.setDestinationInExternalPublicDir("/HongrenFace/download/", downloadName);

7、不要用这种不确定的名字作为文件名了,比如截取url最后一段

8、File apkFile = new File(downloadPath, downloadName); // downloadPath为目录名带"/",
downloadName文件名,不必要加".apk",intent.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");一样可以安装

9、强更对话框后不要再有对话框,否则强更被覆盖

10、ic_launcher从小到大尺寸:48、72、96、144

11、Set up Git on your machine if you haven't already.

mkdir /path/to/your/project  
cd /path/to/your/project  
git init  
git remote add origin https://XXX@bitbucket.org/XXX/XXX.git  
创建你的第一个文件,提交,然后推送到仓库。
echo "建军 汪" >> contributors.txt  
git add contributors.txt  
git commit -m 'Initial commit with contributors'  
git push -u origin master  
干的漂亮,现在你已经完成所有安装步骤!开始编码吧或者创建一个团队并且邀请新人加入吧。
 我有一个已经存在的项目
你的计算机上已经有了一个 Git 仓库?让我们把它推送到 Bitbucket 吧。
cd /path/to/my/repo  
git remote add origin https://XXX@bitbucket.org/XXX/XXX.git  
git push -u origin --all # pushes up the repo and its refs for the first time  
git push -u origin --tags # pushes up any tags  

12、启动mysql:mysqld -install 然后重启,在计算机-服务中找到mysql打开,
连接不上有可能是密码错误,C:\Program Files\MySQL\MySQL Server 5.6\bin>mysqladmin -u root password "XXX"新建密码。 mysqladmin -u root -p password [新密码] 修改密码

13、改变final值的一种解决方法:final String[] rsr = {""}; ... rsr[0] = rs.get(position);

14、单选框的item布局控件:CheckedTextView,其中checkMark="@drawable/cb_selector"自定义样式。

15、view.setOnClickListener,相当于自动设置该控件可点击,如需不可点,需要在setOnClickListener之后view.setClickable(false);

16、不能跨进程回调,需要用handler+message。

17、Inflate(resId , null)不能正确处理item宽和高,所以listview中的item推荐用Inflate(resId , parent, false) 。

18、强大的layer-list叠层+shape实现一个白色背景,左边右边有stroke,底部有另外一种颜色的stroke,顶部没有stroke: 技巧:android:top="-1dp"消除顶部stroke。

<item
    android:top="-1dp">
    <shape android:shape="rectangle">

        <solid android:color="#f5f5f5" />

        <stroke
            android:width="0.5dp"
            android:color="#ebebeb" />

    </shape>
</item>

<item
    android:top="-1dp"
    android:bottom="-1dp">
    <shape android:shape="rectangle">

        <solid android:color="#00ffffff" />

        <stroke
            android:width="0.5dp"
            android:color="#dcdcdc" />

    </shape>
</item>

19、碰到一个非常奇怪不符合逻辑的问题,纠结了一段时间,无果就不要再管,注释掉,以后会自然找到如何解决。别老做重复的事情。

20、

       defaultConfig {
            applicationId "com.dianmi365.hr365" // 更换包名只改此即可
            versionCode version_Code
            versionName version_Name
            minSdkVersion 16
            targetSdkVersion 21
            multiDexEnabled true // 65535
        }

21、alertDialog默认情况下是隐藏软键盘的,要重新显示软键盘,要执行下面这段代码:
alertDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); AlertDialog.setView()则不会出现以上问题。setView()设置占满屏幕宽比较难,使用alertDialog.getWindow().setContentView(view);

22、dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));是去掉自定义view后面的白色框。

23、设置imageview图片注意是setImageResource,不要写成setBackgroundResource。

24、实体类尽量加默认构造方法,否则fastjson解析不出来。

25、listview用holder保证不错位要注意:每个状态在getview里都要if-else写全。

26、ListView中Item加入Button后,导致ListView无法点击。 解决方案:
如果ListView子视图中有Button等抢焦点的控件,那么需要在ListView的xml配置中加入android:descendantFocusability="blocksDescendants", 同时,对Button等控件需要加入 android:focusable="false"。 或者直接把Button换成Textview。

27、java输出:1、数值至少2位,用于时间显示(如03:01):String.format("%02d", int)。2、四舍五入保留两位小数(没有小数也保留两位,不能是int):String.format("%.2f", double)。

28、xml预览自定义view报错,加上:if(isInEditMode()) return;

29、设置TextView的行间距、行高:1、android:lineSpacingExtra 设置行间距,如”8dp”。2、android:lineSpacingMultiplier 设置行间距的倍数,如”1.5″(1是无间距,0会重叠)。

30、给listview设置margin:
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) listView.getLayoutParams(); params.leftMargin = Utility.dip2px(context, 10); params.rightMargin = Utility.dip2px(context, 10);

31、先给AbsListView设置adapter,因为设置头部方法或一些控件(如下拉刷新),这些会measure AbsListView的高度,setAdapter在后会报错!

32、listview的item有layout_marginLeft/right,但是header没有,可以在item的布局在包一层,第二层设置layout_marginLeft/right,
item的根布局设置margin是无效的,listview设置的话header也会有。

33、list里,点一下打开某个UI,再点一下关闭,类似这样的布尔型操作,直接给bean多加一个布尔值控制该ui,if和else写完整,就不会出现ui错位的现象了。

34、一个问题搞不定,回到根源,比如ptr下拉和viewpager冲突,查看ptr上github文档。

35、

drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());  
textView.setCompoundDrawables(drawable, null, null, null);  

以上等同于 textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);

36、更改包名:在app.gradle文件里修改applicationId的值。注意Androidmanifest里要写正确的package="真实包名",下面的Activity包名打点省略是可以的。

37、textView.setText(article.get评论数())这种,如果article.get评论数()是int则会报错,加改成String。

38、视图很奇怪,xml没问题看看是不是java里修改了。

39、gradle保持最新版本(latest.integration)例:compile 'com.umeng.analytics:analytics:latest.integration'

40、别总去思考是不是,直接动手验证一下。

41、用fastjson的话发布正式版不要混淆bean类,加上如:
-keep class com.eebochina.cbmweibao.entity.** {*;}

42、做一个应用logo:512透明背景,圆角矩形从中心128。

43、直接打开与某个qq的对话框:

String url="mqqwpa://im/chat?chat_type=wpa&uin=460697251";  
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));  

44、重启应用:

Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());  
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);

45、int右移x(如:'a'<<3)乘以2的x次方,左移>>除以2的x次方,不进位舍弃小数。

46、include的布局的根ViewGroup不能设置setOnClickListener,只能是这个include的view设置。

47、

ObjectAnimator.ofPropertyValuesHolder(ivPunchCardOk, PropertyValuesHolder.ofFloat("scaleX", 1.6f, 1.0f),PropertyValuesHolder.ofFloat("scaleY", 1.6f, 1.0f)).setDuration(350).start();  

48、fastjson的bean,参数拷贝时,一定要注意参数类型,String还是int:
@JSONField(name = "insurance_city") private String insuranceCity; // 参保地-续保特有-String

49、(boolean... getCalculateRate)这样的参数,不传的话getCalculateRate是不为空的,仅仅只是getCalculateRate.length==0

50、解压apk,在META-INF目录cmd:
keytool -printcert -file META-INF/CERT.RSA 可以查看应用签名信息

51、skd/build-tools/某个版本 配置到环境变量的path里,可以使用aapt命令:aapt dump badging 查看apk版本信息

52、遇到什么问题,猜测一下什么原因,第一件事,试图让他先不报错,有时候会发现自己猜错了,能避免许多无用功。

53、ViewPager+Fragment的框架里,某个Fragment还用到了ViewPager+Fragment,此时FragmentPagerAdapter的FragmentManager需要设置为
getChildFragmentManager() 如:viewPager.setAdapter(new MomFragmentPagerAdapter(getChildFragmentManager()));

54、网络请求返回数据不对,检查:1、是否为特殊UserAgent。2、header是否有遗漏。

55、tmall://page.tm/itemDetail?itemId=21824031395...网页中这样的链接,有天猫客户端跳客户端并进入该商品详情,没有客户端就跳网页详情方法:

   在webview.setWebViewClient里的shouldOverrideUrlLoading首先判断如果是标准的http://或者https://就view.loadUrl(url);return true;
   避免tmall://这样非标准的报错。接着在后面加上:
if (url.startsWith("tmall:") && Utility.validateApp(context, "com.tmall.wireless")) {  
Intent intent = new Intent();  
intent.setAction(Intent.ACTION_VIEW);  
intent.setData(Uri.parse(url));  
startActivity(intent);  
return true;  
}

就会打开天猫客户端。

56、某个字段的释义不要相当然,要去求证确定。

57、布局里 <GridView 里tools:numColumns="4" tools:listitem="@android:layout/simple_list_item_2" 可以预览

58、textview文字添加一个划线,用于高价格对比现在的低价:tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);

59、不一定要完全按照UI来:1、可以有自己的合理想法。2、需求里没有提到的,不必花费时间紧跟UI。

60、改完一处地方,全局搜索一下,还有没有别的地方需要同样修改的。比如:httpHelper.isOfficialUrl(url)是官方的url则添加头部。

61、intent传值,注意参数类型,不要犯低级错误,比如id的类型long-int.

62、从其他工程拷贝类过来,尤其要注意实体类是否正确,比如Comment并不是引用的自定义的,而是默认引用了import org.w3c.dom.Comment;

63、判断dayNow - dayData == 1为昨天,这里的day必须是
int dayData = calendarDate.get(Calendar.DAY_OF_YEAR);不能是DAY_OF_MONTH

64、gridview与ptr滑动不冲突解决方案:

        gvGoods.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mLastItemVisible) {
                    if (!isLoading) {
                        // LoadMore
                        if (page.hasMore()) {
                            LogUtil.log("ptrFrame..page.hasMore()");
                            getGoodsData();
                        } else {
                            ptrFrame.refreshComplete();
                        }
                        isLoading = true;
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (firstVisibleItem == 0) {
                    if (totalItemCount > 0) {
                        if (view.getChildAt(0).getTop() >= gvGoods.getPaddingTop()) { // 真正到顶了就可以滑动外层ptrFrame
                            ptrFrame.disableWhenGridViewMoveNotHead(false);
                        } else {
                            ptrFrame.disableWhenGridViewMoveNotHead(true);
                        }
                    } else { // 数据为空,允许滑动ptrFrame
                        ptrFrame.disableWhenGridViewMoveNotHead(false);
                    }
                } else { // ptrFrame不持有gvGoods的处理,由gvGoods自己处理
                    ptrFrame.disableWhenGridViewMoveNotHead(true);
                }
                mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);

//                gvGoodsScrollProcess(mLastFirstVisibleItem > firstVisibleItem);
                mLastFirstVisibleItem = firstVisibleItem;
            }
        });

65、请求时报:Illegal character in path at index 77 .. 检查url的第77行是否含有空格或者其他非法字符。

66、遇到不对劲,及时纠正,否则以后可能忘记或者造成更大错误。

67、保持一个原则:跳转到详情不要传bean过去,而是传bean的id,在详情页根据id获取info。可以避免:1、详情页操作完返回再进详情页数据未同步。2、后台数据不一致。

68、listview-header几点注意:1、数据为空并不会导致header不显示,不显示的原因有可能是隐藏了listview(BaseListActivity设置了数据为空就显示emptyview)
2、addheader必须写在setadapter前面。 3、设置数据为空显示emptyView时(setNoDataTipShow)记得加上一句判断:ivNoDataTip.getDrawable()!=null

69、再次强调:使用第三方库遇到什么问题回到根源/官方网站/官方github找答案(http://answers.opencv.org/question/16927/detect-if-image-is-blurry/)

70、用UIL加载本地图片文件,file://的形式,后面的字符串必须要做URLDecoder.decode。

71、推送-通知栏几点注意:
1、应用在后台是能收到动态广播的。
2、判断应用是否在后台:

public static boolean isBackground(Context context) {  
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    LogUtil.log("PushService..后台:"+appProcess.processName);
                    return true;
                }else{
                    LogUtil.log("PushService..前台:"+appProcess.processName);
                    return false;
                }
            }
        }
        return false;
    }

3、在收到广播后将后台应用调到前台:

            if (Utility.isBackground(this)) {
                ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
                // moveTaskToFront需要添加权限<uses-permission android:name="android.permission.REORDER_TASKS"/>
                activityManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME);
            }

72、去掉list重复项两个方法:

        1、Set<Object> set = new HashSet<>();
              set.addAll(list);
              list.clear();      
              list.addAll(set);
        2、for(Object obj: sources) {
                if(Collections.frequency(list, obj) < 1)
                list.add(obj);
              }
最近的文章

Android开发路上的踩坑锦集(四)

86、context类都不要弄成static,引用context一定要及时释放,否则容易引起内存泄漏。 85、recyclerview 请求数据计算后adapter.notifyDataSetChan…

Android笔记继续阅读
更早的文章

Android开发路上的踩坑锦集(二)

为方便更新(二)是倒序记录的,因为每一条都有数字标注就不用分割线了。 99、httpClient设置UA,在全局的httpClient设置就好了: defaultHttpClient.getPara…

Android笔记继续阅读
comments powered by Disqus