Android开发小问题汇总二

此排序没有任何优先级或者重要程度。
此笔记只为记录平时开发中碰到的经常用到确不太注意的一些问题,每次用过就忘记,还要重新搜索解决方案,所以在此积累下平时开发中碰到的一些常用而又容易忘记的简单小bug。

本来想一直在同一篇文章中不断更新,可发现简书没办法发布篇幅太大的文章,所以拆开记录,虽然这样零散了,可能不太好查找,但是我会附上对应的链接。

Android开发中小问题汇总一

31、 Android设置“android:clickable="false"无效。
Android开发中在xml文件中设置此属性后,发现点击事件依旧触发, 我们要把 tv_click.setClickable(false);放置在tv_click.setOnClickListener后面执行才可有效,因为设置 setOnClickListener 时候,控件强制令android:clickable="true"。

32、在使用AndroidStudio打包过程中会出现以下错误:"XXX" is not translated in “en” (English) [MissingTranslation]
这个问题是在打包是如果API兼容到7.0及以上,如果Stringxml资源文件没有配置其他语言项时,会出现如此的错误;

  • 解决方案:在app的build.gradle文件中的android{}中加入如下配置然后刷新gradle文件再打包即可:
    android{
      ...
      ...   
     lintOptions {
            checkReleaseBuilds false
            abortOnError false
        }
    }
    

33、为什么ScrollView嵌套ListView,ListView只显示一个Item的高度?
这个问题估计大家面试的时候问到滑动冲突的时候可能都会知道这个,可能问到为什么的时候,估计不细心的人就不知道为什么了,下面简单介绍下:

  • ListView的onMeasure()方法如何计算高的:
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Sets up mListPadding
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        ....... //此处省略部分diamante
        if (heightMode == MeasureSpec.UNSPECIFIED) {
            heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                    getVerticalFadingEdgeLength() * 2;
        }
    
        if (heightMode == MeasureSpec.AT_MOST) {
            // TODO: after first layout we should maybe start at the first visible position, not 0
            heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
        }
    
        setMeasuredDimension(widthSize, heightSize);
        mWidthMeasureSpec = widthMeasureSpec;
    }
    
    可以看到当heightMode == MeasureSpec.UNSPECIFIED时,此事listview的高度则为一行item的高度加上一些padding值。至于heightMode为什么为MeasureSpec.UNSPECIFIED接着往下面看。
  • ScrollView重写了measureChild和measureChildWithMargins方法,在测量自己子View的时候会将高的Mode改成MeasureSpec.UNSPECIFIED。
    @Override
    protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        ViewGroup.LayoutParams lp = child.getLayoutParams();
    
        int childWidthMeasureSpec;
        int childHeightMeasureSpec;
    
        childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft
                + mPaddingRight, lp.width);
        final int verticalPadding = mPaddingTop + mPaddingBottom;
        childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - verticalPadding),
                MeasureSpec.UNSPECIFIED);
    
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
    
    @Override
    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
            int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                        + widthUsed, lp.width);
        final int usedTotal = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin +
                heightUsed;
        final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - usedTotal),
                MeasureSpec.UNSPECIFIED);
    
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
    
    通过代码可以看到Scrollview在测量子View的时候会将对应子View高的Mode改成MeasureSpec.UNSPECIFIED,所以即当ScrollView嵌套ListView,ListView只显示一个Item的高度。
  • 如果解决这种情况下listview显示问题呢?
    将ListView的Mode改成AT_MOST即可。
    public class MyListView extends ListView {
        public FrcListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
               int heightSpec =MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
               super.onMeasure(widthMeasureSpec, heightSpec);
    }
    

34、在使用SharedPreferences使用泛型保存list数据时,碰到com.google.gson.internal.LinkedTreeMap cannot be cast to XXX问题。

  • 正常情况
    public static List<String> getDataList(String tag) {
          List<class> data =new ArrayList<class>();
          SharedPreferences sp = getSharedPreferences();
          String jsonString = sp.getString(tag, "");
          Gson gson =newGson();
          data =  gson.fromJson(jsonString, new TypeToken<List<String>>() {
          }.getType());
          return data;
      }
    
    但是如果使用泛型的方式就会报如下错误 :java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to xxx
  • 解决方案:
    public <T> List<T> getDataList(String tag,Class<T[]> clazz) {
          List<T> datalist=new ArrayList<T>();
          String strJson = preferences.getString(tag, null);
          if (null == strJson) {
              return datalist;
          }
          Gson gson = new Gson();
          datalist = Arrays.asList(gson.fromJson(strJson,clazz));
          return datalist;
      }
    

35、Android 8.0适配报错:Only fullscreen opaque activities can request orientation

  • 方案一:
    找到你设置透明的Activity,然后在对应的theme中将android:windowIsTranslucent改为false。
    <item name="android:windowIsTranslucent">false</item>
    <item name="android:windowDisablePreview">true</item>
    
  • 方案二:
    在AndroidManifest.xml中找到设置透明的Activity去除android:screenOrientation="portrait".

36、Android 8.0适配问题:安装apk权限,更新时下载apk后,不能调出安装界面
在 Android 8.0 中,安装未知应用权限提高了安装未知来源应用时的安全性。此权限与其他运行时权限一样,会与应用绑定,在安装时进行提示,确保用户授予使用安装来源的权限后,此权限才会提示用户安装应用。在运行 Android 8.0 或更高版本的设备上使用此权限时,恶意下载程序将无法骗取用户安装未获得预先授权的应用,所以我们需要加入安装apk文件的权限。
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

37、Android 8.0适配问题:通知栏无法弹出推送消息
NotificationChannel是android8.0新增的特性,如果App的targetSDKVersion>=26,没有设置channel通知渠道的话,就会导致通知无法展示。

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.RequiresApi;

import aihuishou.aihuishouapp.R;

import static android.content.Context.NOTIFICATION_SERVICE;

/**
 * 类名称:NotificationUtil
 * 创建者:Create by liujc
 * 创建时间:Create on 2018/6/1 16:46
 * 描述:通知栏相关工具类
 */
public class NotificationUtil {
    /**
     * 创建通知栏
     * @param context
     * @param notificationId
     * @param intent
     * @param ticker
     * @param title
     * @param content
     */
    public static void createNotification(Context context, int notificationId,Intent intent,String ticker,
                                                 String title,String content){
        Notification.Builder mBuilder = new Notification.Builder(context);
        PendingIntent resultPendingIntent = PendingIntent.getActivity(
                context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent);
        long[] vibrate = new long[]{0, 500, 1000};
        mBuilder.setWhen(System.currentTimeMillis())// 通知产生的时间,会在通知信息里显示
                .setTicker(ticker)
                .setContentTitle(title)
                .setContentText(content)
                .setOngoing(false)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.launcher))
                .setVibrate(vibrate)
                .setAutoCancel(true)
                .setSmallIcon(R.mipmap.launcher);
        NotificationManager mNotifyMgr =
                (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel mChannel = createNotificationChannel(CommonUtil.getChannelName(context),
                    "消息推送", NotificationManager.IMPORTANCE_DEFAULT);
            mNotifyMgr.createNotificationChannel(mChannel);
            mBuilder.setChannelId(CommonUtil.getChannelName(context));
//            mBuilder.setNumber(2);
        }
        Notification notification = mBuilder.build();
        mNotifyMgr.notify(notificationId, notification);
    }

    @TargetApi(Build.VERSION_CODES.O)
    public static NotificationChannel createNotificationChannel(String channelId, String channelName, int importance) {
        NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
        channel.setShowBadge(false);
        return channel;
    }
    /**
     * 重定向到通知渠道的设置
     * @param context
     * @param channelId  通知渠道的id
     */
    public static void jumpToNotificationChannelSetting(Context context, String channelId){
        Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
        intent.putExtra(Settings.EXTRA_CHANNEL_ID,channelId);
        intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
        context.startActivity(intent);
    }
    /**
     *
     * @param context
     * @param channelId   通知渠道的id
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static void deleteNotificationByChannelId(Context context, String channelId){
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        mNotificationManager.deleteNotificationChannel(channelId);
    }
}

38、Fragment报错:android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public
解决方案:参考 https://stackoverflow.com/questions/10450348/do-fragments-really-need-an-empty-constructor

39、Fragment 重叠 问题
调查原因:
主要还是因为Fragment的状态保存机制,当系统内存不足时,Fragment的主Activity被回收,Fragment的实例并没有随之被回收。
Activity被系统回收时,会主动调用onSaveInstance()方法来保存视图层(View Hierarchy),所以当Activity通过导航再次被重建时,之前被实例化过的Fragment依然会出现在Activity中,然而从上述代码中可以明显看出,再次重建了新的Fragment,综上这些因素导致了多个Fragment重叠在一起。

解决方案:
在对应的activity中重写onSaveInstanceState方法,如下:

//解决fragment
@SuppressLint("MissingSuperCall")
@Override
public void onSaveInstanceState(Bundle outState) {
    //如果用以下这种做法则不保存状态,再次进来的话会显示默认的tab
    //  super.onSaveInstanceState(outState);
}

40、ARouter there's no route matched解决方法
path都是”/app/xxxx/”,Aouter 要求path必须有至少两级的路径,是因为Arouter在寻找route的时候,是通过第一级路径,也就是这里的”app”来寻找的。Aouter通过”app”找到了route,并且在groupIndex中删除了这个路径,代表已经加载到了内存。
不同的module使用了相同的一级路径,在Arouter第一次寻找到route的时候便删除了这个一级路径的group,因为一级路径的重复,再调用另一个module的一级路径是”app”的路由时,由于之前Warehouse.groupsIndex已经删除,便导致了there’s no route matched的错误。

41、Android WebView允许web使用时html5自适应屏幕标签
解决方案:

settings.setUseWideViewPort(true); 
settings.setLoadWithOverviewMode(true);
  • Html5中常用的 viewport meta 如下:
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    1. width : 控制viewport的大小,可以指定一个值,如600, 或者特殊的值,如device-width为设备的宽度(单位为缩放为100%的CSS的像素)
    2. height : 和width相对应,指定高度
    3. initial-scale : 初始缩放比例,页面第一次加载时的缩放比例
    4. maximum-scale : 允许用户缩放到的最大比例,范围从0到10.0
    5. minimum-scale : 允许用户缩放到的最小比例,范围从0到10.0
    6. user-scalable : 用户是否可以手动缩放,值可以是:①yes、 true允许用户缩放;②no、false不允许用户缩放

42、android layout_gravity属性设置失效的问题
调查原因:

  • 当父布局LinearLayout设置android:orientation="vertical"时, 只有水平方向的leftrightcenter_horizontal设置起作用,垂直方向的设置不起作用。
  • 当父布局LinearLayout设置android:orientation="horizontal" 时, 只有垂直方向的topbottomcenter_vertical设置才起作用,水平方向的设置不起作用。

43、Android Studio 自动导包无效及其他快捷键无效问题
问题描述:突然Android Studio不知道怎么回事,自动导包功能,快速查找类等快捷键也无效。
解决方案:清理Android Studio的缓存,选择工具栏 File --> Invalidate Caches /Restart... --> Invalidate and Restart 重启Android Studio即可。

44、Failed to resolve: com.android.support:appcompat-v7:27.+ 报错解决方法
问题描述: 用Android Studio新建一个android项目完成后报错Failed to resolve: com.android.support:appcompat-v7:27.+
解决方案:
新建Android项目中的app -> build.gradledependencies 默认配置如下:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:27.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}

针对Android Studio 2.3版本应该在项目根目录下 Project -> build.gradle 中的 allprojects配置如下:

allprojects {
    repositories {
        jcenter()
        maven { url "https://maven.google.com" } //(新增)
    }
}

针对Android Studio 3.0版本应该在项目根目录下 Project -> build.gradle 中的 allprojects配置如下:

allprojects {
    repositories {
        jcenter()
        google()
    }
}
  1. Glide加载网络图片出现模糊问题
    项目中使用glide框架加载网络图片到ImageView中出现了模糊,仔细检查后才发现是设置ImageView大小导致的,解决方案就是将ImageView的宽度动态计算设置宽高,获取网络图片后计算图片大小
//获取图片真正的宽高
        Glide.with(context)
                .load(imgUrl)
                .asBitmap()//强制Glide返回一个Bitmap对象
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
                        int width = bitmap.getWidth();
                        int height = bitmap.getHeight();
Glide.with(AppApplication.get()).load(url).asBitmap().format(DecodeFormat.PREFER_ARGB_8888).override(width, heigh).into(imageView);

                        }
                    }
                });


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容