愚蠢bug录——Android

这篇博文用来记录我自己犯过的很2很傻的bug(很很很低级的)或不合理的操作。

0.遇到问题想马上解决(急躁)

这个是最根本,最核心的问题,遇到bug或者自己意料之外的情况,绝对不能认为这是个小问题,能几分钟解决,越是这样想,越是急躁,最后的结果往往是急躁的度过1~2小时,然而问题却没解决,自己还很烦恼!

解决方案:必须冷静,好好的分析逻辑,平心静气的检查自己的代码,不急不躁,才能解决问题!


1.Log.v(“”)
贪图方便直接调用封装好的log.v(“”)。
当调用的地方多了,又想取消打印的时候找不到是在哪里调用的。
在查找时白白浪费大量无用的精力和时间!

解决方案:以后打印要记得使用Log.v(TAG,”“);这样才能知道是在哪里调用,以后方便取消这些调用。


2.使用600dp
在平板上开发,为了达到效果让一个视图的高为600dp,结果是平板上显示正常,可是到了手机(小设备)结果是显示一片空白!还以为是系统不兼容,发现这个原因浪费了2个多小时!

解决方案:不使用超过100dp的设置!配合使用layout-sw600dp和layout等等,适配不同大小的设备。


3.sqlite插入数据报错
报错如下图:
这里写图片描述

经过查询代码,竟然是我调用Log.v(“”)执行了一次插入语句,然后return时又执行了一次,由于Id是主键,不能重复,所以报错了。。。;

原代码:
这里写图片描述

解决方案:使用Log.v时不要使用方法,要使用成员!

4.uri转BitMap时, 一直nullpointer exception!
ImageView img = findViewById(R.id.image);
img.img.setImageBitmap(bm);//这行一直报错

因为我没做过这种类型的操作,我一直以为是转的时候出错了!
结果试了网上很多种方式,全部报错!

就在我崩溃的时候,tm的发现了是R.id.image错了!!!!!,原来我在xml声明的是”@+id/img”…我的心好累TvT,也算是弱智bug的老大了.大概花了3个小时搞这个东西。

解决方案:写代码是严谨的!不能贪快!!!!每一个地方都要细致的操作!!!

顺便记录: uri转bitmap
使用如下

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
                startActivityForResult(intent, 100);

在onActivityResult得到 uri

uri格式有2种
1. content://com.android.providers.media.documents/document/image%3A42
2. /storage/emulated/0/DCIM/Camera/IMG_20160206_234530.jpg

第一种获得的方法:

    Uri url = data.getData(); //样子--》content://com.android.providers.media.documents/document/image%3A42

第二种的获得方法
把第一种的uri当做参数传入

@SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] { split[1] };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     * 
     * @param context
     *            The context.
     * @param uri
     *            The Uri to query.
     * @param selection
     *            (Optional) Filter used in the query.
     * @param selectionArgs
     *            (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
            String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = { column };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

使用第一种的uri转bitmap

img = (ImageView) findViewById(R.id.img);

        Uri url =  (Uri) getIntent().getExtras().get("url");
         ContentResolver resolver = getContentResolver();
         Bitmap bm = null;
            try {
                bm = MediaStore.Images.Media.getBitmap(resolver, url);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }     
            img.setImageBitmap(bm);

6.对Model(实体bean)进行操作(2016-05-29)

Person a;
a.getName();// 这样做会报错,因为a没有被初始化
Person a = new Person();
a.getName();// 这样system.out.printf打印出来得到 null
            // 不代表a.getName = "null",实际上是别的类型,可能是null类型相关的
            // 要判断a里面的name是否被赋值,要利用
            // String.valueOf(a.getName()).equals("null")
            // 如果直接a.getName().equals("null")会报异常,
            // 因为此时a.getName得到的返回值并不是String类型的
            // 另外一点,String.valueOf(null)会报错
            //
            //
            /////


7.ScrollView里面顶部的控件被挤出去了(下拉能看见)2016/06/07更新

解决方案:scrollView一般嵌套一个LinearLayout,把LinearLayout的 android:layout_gravity=”center_vertical”属性去掉即可


8.想对ScrollView使用代码模拟手势操作 2016/06/16

比如希望控制代码达到手势上划的效果。
使用scrollto或scrollby都是不正确的。会导致某些内容看不到了,相当于被剪切了。
经查询资料:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0911/1680.html

使用offsetTopAndBottom()可以完美解决!

mScrollLayout.post(new Runnable() {
            @Override
            public void run() {
                mLinearLayout.offsetTopAndBottom(-monthView.getMeasuredHeight());
                mScrollLayout.postInvalidate();
            }
        });

2016/6/21更新

offsetTopAndBottom只是效果位移,但是不是模拟手势!
以下代码才是真正解决!!!!!!!!
注意,如果View没有测量完成,也是无效的!

思路:

开一个线程,循环判断View.getMeasuredHeight(),如果不等于0,代表测量完成,这次使用handle发送消息,然后调用viewGroup.onTouchEvent(event);

Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            actionMove(mScrollLayout);
        }
    };
    public void hideMonthView() {
        // 模拟手势上划
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(monthView.getMeasuredHeight() == 0) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                    handler.sendEmptyMessage(1);
            }
        }).start();
    }

    /**
     * 模拟滑动事件
     * 隐藏monthview
     * @param viewGroup
     */
    public  void actionMove(ViewGroup viewGroup) {
        final long downTime = SystemClock.uptimeMillis();
        final MotionEvent downEvent = MotionEvent.obtain(
                downTime, downTime, MotionEvent.ACTION_DOWN, 788, monthView.getMeasuredHeight(), 0);
        final MotionEvent Event3 = MotionEvent.obtain(
                downTime, downTime+300, MotionEvent.ACTION_MOVE,  785, 0, 0);
        final MotionEvent upEvent = MotionEvent.obtain(
                downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 850, 0, 0);
        viewGroup.onTouchEvent(downEvent);
        viewGroup.onTouchEvent(Event3);
        viewGroup.onTouchEvent(upEvent);
        downEvent.recycle();
        Event3.recycle();
        upEvent.recycle();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值