汪建军的博客

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

Android developer, sometimes thinking, sometimes try it.


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

86、context类都不要弄成static,引用context一定要及时释放,否则容易引起内存泄漏。

85、recyclerview 请求数据计算后adapter.notifyDataSetChanged();,如果这个计算时间过长,放到线程里,但是要注意不能在线程里直接datas.clear();
会报java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 34(offset:34).state:35 需要定义一个临时datas,计算完成后,抛到主线程addAll。

84、recyclerview item的显示都要根据bean的字段来,不能根据itemview.textview的文字来判断,否则会错位。

83、文件夹的大小是8192,做大小判断不要犯低级错误,要递归求文件夹下所有总和。

82、https下载失败可能是手机系统时间有问题导致证书失效。

81、分享网页到微信,图片msg.thumbData尺寸太大无法调起,需要缩小到100*100

80、qq分享、授权登录要得到回调一定要写onActivityResult:

if (requestCode == Constants.REQUEST_QQ_SHARE || requestCode == Constants.REQUEST_APPBAR) {  
            Tencent.onActivityResultData(requestCode, resultCode, data, baseUiListener);
        }

79、两个小问题:HashMap的keySet是乱序,用LinkedHashMap。intent传的是值。

78、abiFilters "armeabi-v7a"后调用C方法报UnsatisfiedLinkError之类架构错误,尝试把编译环境降到23.0.3、2.10、2.2.3,跑一遍后直接拿77的so文件。
25.0.2、3.4.1、2.3.0有很多坑需要注意,Jenkins、NDK都有可能遇到。

77、直接可用的so文件是build\intermediates\ndk\release\obj\下的,而不是...\lib\下的

76、简单JavaBean和对应的HashMap JSONUtil.toJSONString 的结果是一样的。

75、Html.fromHtml无法换行,无法改变字体大小

74、

 <com.open.androidtvwidget.leanback.recycle.RecyclerViewTV
        android:id="@+id/rcv_course"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/d_135"
        android:layout_marginLeft="@dimen/d_75"
        android:layout_marginRight="@dimen/d_18"
        android:layout_marginTop="@dimen/d_140"
        android:layout_toLeftOf="@+id/iv_info"
        android:background="@color/transparent"
        android:fadeScrollbars="false"
        android:focusable="true"
        android:paddingRight="@dimen/d_10"
        android:scrollbarStyle="outsideInset"
        android:scrollbarAlwaysDrawVerticalTrack="false"
        android:scrollbarThumbVertical="@drawable/scroll_bar"
        android:scrollbarTrackVertical="@drawable/bg_scroll_bar"
        android:scrollbars="vertical"
        tools:listitem="@layout/item_center_homework"/>

73、generate signed apk要把v1、v2都勾上打的包才能正常跑。直接运行要把instant run关掉,output里的apk才能直接拿出来安装。

72、用RecyclerView的item的高度要设置为wrap_content,还要记得加分隔符。

71、recyclerview移动到指定item并将其置顶:linearLayoutManager.scrollToPositionWithOffset(position, 0);

70、ColorDrawable dw = new ColorDrawable(activity.getResources().getColor(R.color.bgwhite90));
pop.setBackgroundDrawable(dw); // 不设置这个点击PopupWindow外将不会使PopupWindow dismiss

69、android studio上移包前一定要先备份或者传svn,选择第二个存在包下文件全部被删的bug。

68、bundle经验:1、Parcelable里没有read/writeToParcel的字段无法传输。2、不要传输bitmap等较大数据,最好存文件传地址,
或者bitmap.compress(Bitmap.CompressFormat.JPEG, 20, stream);//这种其实也容易FAILED BINDER TRANSACTION !!! (parcel size=xxx),quality越小越安全

67、options.inJustDecodeBounds = true;会使BitmapFactory.decode..只获得宽高,不会生成bitmap,是效率较高的获取bitmap属性的方法。
options处理完,需要调用inputStream.close();然后再次初始化inputStream,BitmapFactory.decodeStream才不会返回null。

66、RGB_565ARGB_8888不会有文件大小差异。quality80会比100文件大小降低20%,但是会失真,看起来比100的暗。

65、给白色文字加一个灰色小阴影,可以确保在白底上看清:mShowText.setShadowLayer(1, 1, 1, getResources().getColor(R.color.text_hint));

64、synchronized能解决camera时不断进行复杂操作,同时高频进入返回偶尔闪退问题,但是返回按钮(当之前可能闪退时)需要过一段时间才生效。
不要在camera辅助类里写synchronized方法,界面高频操作没有结合synchronized容易闪退,最好是都不写。

63、camera.setOneShotPreviewCallback会与camera.setPreviewCallback冲突,导致setPreviewCallback调用几次就不再调用,注释掉setOneShotPreviewCallback可恢复正常。

62、retrofit下用ip调试,比如调用【10.1.7.165:8000/api/ocr/idcard/】这样的接口,
new一个retrofit时.baseUrl("10.1.7.165:8000/")会报Illegal URL with retrofit,baseUrl必须要http开头, 在call里@POST("10.1.7.165:8000/api/ocr/idcard/")也无效, 必须要在ip前加上http://,如【@POST("http://10.1.7.165:8000/api/ocr/idcard/")】

61、merge只能inflate(R.layout.itemddcard, llPicContainer, true);。不能用于多次添加,会报:The specified child already has a parent.

60、retrofit不要在intercept里做有网缓存,上传速度很快,删除很快发event就会不请求。

59、测试包变成老版本的原因是手机静默升级,测试的时候需要关掉自动升级。

58、app上web问题用postman模拟,看看请求头部、返回头部是否异常,增删某些头部项对比检测。

57、entity里所有自定义的字段要用transient过滤掉,不序列化,也不会被gson解析。

56、列表内容改变技巧:在bean里自定义一个boolean变量,点击在onclick里更改ui,更改boolean,adapter里if-else对应好,可以避免使用notifyDataSetChanged。

55、Relativelayout下扩大"展开"按钮技巧例子:

<TextView
    android:id="@+id/tv_all"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/tv_name"
    android:layout_below="@+id/tv_content"
    android:layout_marginTop="0dp"
    android:drawablePadding="5dp"
    android:drawableRight="@drawable/expand"
    android:paddingRight="20dp"
    android:paddingTop="20dp"
    android:paddingLeft="15dp"
    android:layout_marginLeft="-15dp"
    android:paddingBottom="11.5dp"
    android:layout_marginBottom="-11.5dp"
    android:text="展开"
    android:textColor="@color/main_blue_deep_150"
    android:textSize="13sp"
    android:visibility="gone" />

<LinearLayout
    android:id="@+id/ll_discuss2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/tv_name"
    android:layout_below="@+id/sp1"
    android:layout_marginRight="12dp"
    android:layout_marginTop="0dp"
    android:orientation="vertical"
    android:visibility="visible">

54、解决overridePendingTransition退出无效:在onCreate里写一次,在finish后面或者super.onBackPressed()后面再写一次。

53、public static的值如果是另一个public static的值拼接起来的,另一个改变,这个也不会改变。

52、状态栏一般是25dp

51、自定义view的alertdialog不要瞎折腾,老老实实用:

        Window window = alertDialog.getWindow();
        if (window != null) {
            window.setContentView(view);
            window.setGravity(Gravity.CENTER);
            WindowManager.LayoutParams layoutParams = window.getAttributes();
            layoutParams.width = (int) (SupportUtility.getDisplayManager(mActivity).widthPixels * 0.75);
            layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
            window.setAttributes(layoutParams);
        }

50、在BottomTabbar的gridView.setOnItemClickListener里viewPager.setCurrentItem(position, false); 加上false去掉滑动动画效果,能解决一级页面首次跨越切换卡的问题。

49、遇到如打release包有网请求,直接运行没网络请求的奇怪情况:1、检查release和debug定义的boolean有何影响。2、清除app模块的build文件夹,重新build。3、对比svn上的,将根build.gradle和app的build.gradle回滚到最初未添加gradle插件的情况。

48、用了umeng统计,在Andrmanifest里配置了渠道码:
android:name="UMENG_CHANNEL" android:value="${channelName}"/> 在获取渠道码的时候应该:applicationInfo.metaData.getString("UMENG_CHANNEL");注意名称对应。

47、控件设置动画,如果加了animation.setFillAfter(true);又想要在AbsListView.OnScrollListener里复位,记得先view.clearAnimation();

46、不要在子模块配置混淆,否则app模块无法引用方法

45、有视频播放的页面记得在onCreate里加上getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);保持屏幕常亮。
(这个不必像requestWindowFeature(Window.FEATURE_NO_TITLE);非得放在setContentView之前。)

44、calendar的月份要减一

43、有样式的自定义控件,如Alertdialog,放到app模块下。

42、想统一在BaseActivity里加一个Snackbar,报错:You need to use a Theme.AppCompat theme (or descendant) with the design library.
解决办法:manifest里application的android:theme要是一个继承自AppCompat的activity android:theme="@style/AppTheme",并且加上:

41、不要太依赖IntentService的自我销毁,所有start启动的service,一定要在MainActivity的onDestroy里写stopService。一切在service的子线程里更新ui的操作都要判断应用或者service是否已被杀死。

40、上传、下载文件的service的onStartCommand返回START_REDELIVER_INTENT

39、注意细节,存文件总考虑到有些手机没有SD卡。

38、上线前多做混淆测试,后面几个稳定的release包都打混淆的给测试,#腾讯云直播未加上这句会崩溃: -keep class com.tencent.**{ *; }

37、 java.io.IOException: The same input jar [C:\svn\hrloo\app\libs\alipaySdk-20161009.jar] is specified twice.
去掉proguard-rules.pro里的-libraryjars libs/alipaySDK-20161009.jar,因为在android studio中,已经默认将jar包不进行混淆了。

36、判断用户是否开启了重力感应(屏幕旋转按钮):

    int screenchange = Settings.System.getInt(context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION); // 0关、1开,(红米3s是反的)
    相应的设置:Settings.System.putInt(activity.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION, 0);
    视频播放页面用户开启重力感应固定不旋转,关闭则跟随旋转:1、OrientationEventListener不管用户是否关闭屏幕旋转都可以监听到,在这里进行上面的判断。2、manifest依然设置android:screenOrientation="portrait"。3、根据监听activity.setRequestedOrientation(screenOrientation);

35、AlphaAnimation alphaAnimation = new AlphaAnimation(0.2f, 1f);
alphaAnimation.setFillAfter(true); alphaAnimation.setDuration(270); llMenu.startAnimation(alphaAnimation); 设置动画之后 llMenu.setVisibility(GONE); 之前要调用 llMenu.clearAnimation();,否则隐藏不掉

34、etName.setSelection(cName.length()); 如果etName的maxLength=20,而cName.length()超过20,这里会报越界:setSpan (21 ... 21) ends beyond length 20

33、再次提醒:不管是listview还是recyclerview的adapter里设置视图,if与else一定要成对,只是在if里更改ui就会错位。

32、微信支付的一个坑:开发时工程的包名是com.hrloo.mobile,配置了androidApplicationId = 'com.hrloo.study',所以打包出来的包名是com.hrloo.study。
微信的回调是用的反射,必须为WXPayEntryActivity配置一个真实的study包,WXPayEntryActivity正确的位置是com.hrloo.study.wxapi包下,这样才能正确回调onResp。 调起支付,拿到后台的签名数据后直接如下即可: IWXAPI wxapi = WXAPIFactory.createWXAPI(activity, Constants.WXAPPID); PayReq req = resultData2PayReq(result.getData()); if (req != null) { wxapi.sendReq(req); } 不需要写全局变量,不需要调用registerApp()方法,也不需要弄一个官方demo里的广播AppRegister。

31、Android Studio 2.2+,编译bug:File 'C:\svn\ehr\app\build\intermediates\res\resources-ehrdev-debug-stripped.ap' specified for property 'resourceFile' does not exist.
解决办法:shrinkResource=false。加快编译速度: 1、app模块gradle的android下: dexOptions { preDexLibraries = true incremental true javaMaxHeapSize "4g" } 2、gradle.properties下: org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx6096m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 3、设置里:Build-> Gradle、Compiler下全部勾上,全部选择本地,配置--offline

30、使用AsyncHttpClient解决StringEntity中文乱码:entity = new StringEntity(new JSONObject(map).toString(), "UTF-8");

29、Gson几点注意:
1、获得JsonObject的String形式,直接JsonObject.toString(); 不需要Gson.toJson(Object)。 2、像三茅的接口为空返回""(就是这样两个点,不是空字符串),会被认为是String而解析不了为JsonElement,Result的data还不能直接指定JsonElement,只能是泛型T,get方法如下:

    public String getData() {
        String dataStr = JSONUtil.toJSONString(data);
        //dataStr = dataStr.replace("\\", ""); // 一般不这样写,个别的(比如三茅首页的ads,用fastjson存的缓存)要这样写
        //dataStr = dataStr.replace("\"{", "{");
        //dataStr = dataStr.replace("}\"", "}");
        if ("\"\"".equals(dataStr)) {
            dataStr = "";
        }
        return dataStr; // 之前不是String这样写的:return new JsonParser().parse(JSONUtil.toJSONString(data)).toString();
    }

对于list

    public String getListString() {
        String listStr = JSONUtil.toJSONString(list);
        if ("\"\"".equals(listStr) || !listStr.startsWith("[") || !listStr.endsWith("]")) {
            listStr = "";
        }
        return listStr;
    }
    得到纯粹作为String类型的data,不包含前后的"",比如得到订单信息的接口,整个data内容作为字符串参数传给支付宝
    String dataStr = JSONUtil.parseObject(getData(), String.class);

对应的根据key获取字段的方法
public String getDataStr(String key){
    return new JsonParser().parse(getData()).getAsJsonObject().get(key).toString();
}
3、基本类型全部定义为String,否则不规范的为空返回会报错,通过get方法获得真实的类型:
public int getCat_id() {
    if (TextUtils.isEmpty(cat_id)) return 0;
    return Integer.parseInt(cat_id);
}

28、fastjson什么都可以解析为String,gson不行,它区分JsonObject和JsonArray,或者统一用基类JsonElement。gson可以自由修改字段的get/set,fastjson不行。

27、socket代理方式缓存m3u8就不能再让手机连fiddler了。

26、Android下字符串去掉特殊符号:str.replaceAll("[\p{Punct}\p{Space}]+", "");

25、如果android.support.design.widget.TabLayout报错,在manifest中包含它的activity里添加:android:theme="@style/Theme.AppCompat.Light"

24、由一个bitmap生成另一个bitmap:

        Bitmap bitmapProcess = Bitmap.createBitmap(bitmapOriginal.getWidth(), bitmapOriginal.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmapProcess);
        canvas.drawBitmap(bitmapOriginal, 0, 0, null);

只能用以上方法,其他的方法(如:bitmapProcess=Bitmap.createBitmap(bitmapOriginal,0,0,bitmapOriginal.getWidth(),bitmapOriginal.getHeight());)最后imageview显示出来都是bitmapProcess

23、Gradle编译ndk:
Windows下:

    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        commandLine "$android.ndkDirectory\\ndk-build.cmd",
                '-C', file('src/main/jni').absolutePath,
                '-j', Runtime.runtime.availableProcessors(),
                'all'
    }

Linux下:

    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        commandLine "$android.ndkDirectory/ndk-build",
                '-C', file('src/main/jni').absolutePath,
                '-j', Runtime.runtime.availableProcessors(),
                'all'
    }

22、Gradle常用命令:
gradlew -v 版本号
gradlew clean 清除app目录下的build文件夹
gradlew build 检查依赖并编译打包,把debug、release环境的包都打出来,如果正式发布只需要打Release的包,用下面的assemble命令
gradlew assembleDebug 编译并打Debug包
gradlew assembleRelease 编译并打Release的包
gradlew installRelease Release模式打包并安装
gradlew uninstallRelease 卸载Release模式包

21、在自定义的Application里注册registerActivityLifecycleCallbacks,onActivityStarted里计数+1,onActivityStopped里计数-1,计数变成0说明应用到了后台,
计数由0->1说明应用由后台返回前台(不能只判断变成1)。 如果在MainActivity中使用getApplication().registerActivityLifecycleCallbacks(...)注册,要注意: (1)如果MainActivity不是第一个activity,计数变成-1才说明应用到了后台。 (2)创建DialogFragment之类不能使用默认的getFragmentManager(),要使用注册时回调里的activity.getFragmentManager(),也不能使用MainActivity的生命周期。 (3)不要在回调的stop里操作fragment之类,容易报错:Can not perform this action after onSaveInstanceState。

20、动态广播监听home键:

filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);  
在onReceive里判断action.equals(Intent.ACTION_MAIN) // 这里与注册的不是一致的,不能用ACTION_CLOSE_SYSTEM_DIALOGS判断
String reason = intent.getStringExtra("reason");  
// reason:"homekey"为按下home,"lock"为锁屏,"recentapps"为长按Home键 或者 activity切换键,"assist"为长按Home键

19、替换点:String.replace(".", "_"); 按点拆分:String.split("\.");

18、只打包含指定abi的包:

    productFlavors {

        "ehr_test" {
            manifestPlaceholders = [channelName: "EB000"]
            ndk {
                abiFilters "armeabi-v7a"
                abiFilters "arm64-v8a"
                abiFilters "armeabi"
            }
        }
...
}

17、拆分多个apk,每个仅支持单独的abi,在最外的android层内写:

    splits {
        abi {
            enable true
            reset() // 没有这一句所有的apk都会有
            // 全部:arm64-v8a armeabi armeabi-v7a x86 x86_64 mips mips64
//            include 'armeabi', 'armeabi-v7a', 'arm64-v8a'
            include 'armeabi-v7a'
//            exclude 'x86', 'mips' // 没用
//            universalApk true // 默认false,表示不打包通用包(包含所有abi)
        }
    }

16、Des加解密例子:

    public static void DesTest() {
        byte[] desEn = encodeDes("hrloo.com".getBytes(), "dK4fK0Jj");
        byte[] desDn = Base64.decode("jbrUOBFq+lOXrpMDTpIkeA==", Base64.NO_WRAP);
        System.out.println("password加密=" + Base64.encodeToString(desEn, Base64.NO_WRAP));
        System.out.println("password解密=" + new String(decodeDes(desDn, "dK4fK0Jj")));
    }

    /**
     * 对字符串加密
     */
    public static byte[] encodeDes(byte[] data, String encodeKey) {
        try {
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding");
            DESKeySpec dks = new DESKeySpec(encodeKey.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // key的长度不能够小于8位字节
            Key secretKey = keyFactory.generateSecret(dks);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DES算法,解密
     */
    public static byte[] decodeDes(byte[] data, String decodeKey) {
        try {
            DESKeySpec dks = new DESKeySpec(decodeKey.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // key的长度不能够小于8位字节
            Key secretKey = keyFactory.generateSecret(dks);
            //DES/ECB/PKCS5Padding
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(data);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

15、会动的drawable,加载动画-转菊花,放在drawable目录下直接引用:

<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"  
    android:drawable="@drawable/progress_image"
    android:pivotX="50%"
    android:pivotY="50%" />

14、HttpURLConnection下载例子,带进度回调监听:

    public void download(final String url, final String destinationPath) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    notifyProgressOnUiThread(0, 1); // 开始进度为0
                    File file = new File(destinationPath);
                    long fileLength = 0;
                    if (file.exists()) {
                        fileLength = file.length();
                    }
                    HttpURLConnection urlConnection;
                    URL urlObj = new URL(url);
                    urlConnection = (HttpURLConnection) urlObj.openConnection();
                    int totalSize = urlConnection.getContentLength();

                    if (fileLength != totalSize) {
                        FileOutputStream fileOutput = new FileOutputStream(file); // 这一句会将有内容的file置空
                        int downloadedSize = 0;
                        byte[] buffer = new byte[BUFFER_LEN];
                        int bufferLength;
                        InputStream in = new BufferedInputStream(urlConnection.getInputStream());

                        while ((bufferLength = in.read(buffer)) > 0) {
                            fileOutput.write(buffer, 0, bufferLength);
                            downloadedSize += bufferLength;
                            notifyProgressOnUiThread(downloadedSize, totalSize);
                        }
                        fileOutput.close();
                        saveCache(destinationPath);
                    }

                    urlConnection.disconnect();

                } catch (IOException e) {
                    notifyFailureOnUiThread(e);
                }

                notifyProgressOnUiThread(1, 1); // 结束进度为100%
                notifySuccessOnUiThread(url, destinationPath);
            }
        }).start();
    }

13、IntentService没有处理事务会被自动销毁,无法收到消息,无论是LocalBroadcast还是EventBus,所以需要频繁和UI交互的后台任务不要用IntentService。一组网络请求用的retrofit,本来就是异步的,还用IntentService额外开一个线程就很怪异,而且容易出错。

12、list的remove方法依赖于bean的equals,复写bean的equals方法要注意比较的字段一定要能区分唯一(EmployeeDataDetail有的没有key字段)

11、list的contains方法依赖于bean的equals,复写bean的equals方法,可用于该list的排重。

10、正则匹配举例:

    // 仅截取首次出现的数字,如56465412_654.jpg返回56465412
    public static String getNumbersPrimo(String content) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            return matcher.group(0);
        }
        return "0";
    }

9、不要并发修改list(在list的for循环里删除list的元素)

8、qq授权通过get_user_info获取用户信息失败,调用增量授权“all”就可以了:

                        JSONObject jsonResponse = (JSONObject) o;
                        int ret = jsonResponse.getInt("ret");
                        if (ret == 100030) {
                                mTencent.reAuth(context, "all", baseUiListener);
                            }

7、用fastjson的话,实体类一定不能混淆,注意

-keep class com.hrloo.mobile.entity.**{ *; }
-keep class com.hrloo.mobile.widget.ad.**{ *; }

6、传给方法里的变量都是传值,即使传的是个final变量,也能在方法里改变这个变量的值。

5、打开本包内assets目录下的index.html文件:

webView.loadUrl("file:///android_asset/index.html");  // 注意不带s,还要有READ_EXTERNAL_STORAGE权限  

4、double乘法转int不丢失精度方法:

double amount = 2553.18d;  
int intMathRound = (int) (Math.round(amount * 100));  

3、latest.integration有风险,而且不一定就比写死版本高。

2、第三次提醒,出BUG,回到问题根源,千万不要去瞎猜,浪费时间,就在报错的log附近前前后后看。千万不要想当然,直接拿过报错的机子重现去找问题!

1、解决textview设置android:ellipsize="end"省略号后面还有残缺字符串的问题:holder.tvInfo.setText(Html.fromHtml(bean.getIntro()));

最近的文章

Android实现图片相似度

最近公司有一个需求,就是希望能判断用户提交的照片是否是身份证的正面或者反面。可以通过预设一张拍摄清晰的身份证正面或者反面,来对比是否相似,那么问题就转化为如何计算两张图片相似度。找到一篇阮一峰老师当年…

举个例子继续阅读
更早的文章

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

(三)会有一些想问题的方法。 1、给Listview设置高度:android:minHeight="50dp" 2、android studio的assets包是在main下面和“java”包同一层的…

Android笔记继续阅读
comments powered by Disqus