文档章节

Android中遇到的好的博文

Ev4n
 Ev4n
发布于 2016/07/25 13:13
字数 2923
阅读 35
收藏 0

(一)Andoird Studio 错误: 非法字符: '\ufeff'

参照链接这里解决。原因是as无法识别BOM的问题。人生中第一次遇到这个问题是大学时写PHP,那时候就牢牢的记住个了。时隔这么多年,在另一款编辑器另一种语言中又遇到了,缘分啊!

(二)关于AlertDialog

这里一模一样的内容) 有关于AlertDialog的基本使用,基本可以参考到了。不过更好的是如何与AlertDialog交互的问题,有一篇文章写得特别好,但是找不到了。

在onClick(DialogInterface,int,int which)中,可以通过DialogInterface的getId来区分弹出的AlertDialog,按键则通过which了。这种情况适合于将所有的AlterDialog的onClick回调全部绑定到自身的情况了。

(三)ListView

这里ListView使用的文章,而这个是关于android.R.layout里面定义的与listview有关的那部分xml说明,值得参考。这个详细的介绍了adapter情况,值得回味一下

简书中的这篇文章简单却很有效的介绍了BaseAdapter的用法,比其他的更加有效,看完之后就基本了解了其原理及应用


(四)自带图标

这里是有关android自带的系统图标,可以通过android.R.drawable/访问,至少用作临时的place holder也可以嘛!

(五)Android问题与之thisActivity.this的区别

这里有关Activity.this与this区别。写过js所以的对于闭包有些害怕,但在这里于是乎还是一目了然。

        fab_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOptStatus = OperationStatus.Other;
                if (mArea.getCount() == 0) {
                    Toast.makeText(MainApplication.getContext(), "请先圈定范围", Toast.LENGTH_SHORT).show();
                } else {
                    View vv = LayoutInflater.from(MainApplication.getContext()).inflate(R.layout.save_line_dialog, null);
                    save_name_et = (EditText) vv.findViewById(R.id.save_line_et);
                    save_line_ad = new AlertDialog.Builder(getActivity())
                            .setTitle("输入名称")
                            .setView(vv)
                            .setPositiveButton("保存", iActivity.this)
                            .setNegativeButton("取消", null).create();
                    save_line_ad.show();
                }
            }
        });

(六)ListView的onItemLongClick不被触发

这里表述了这两者(LongClick和Click)的过程。默认情况下as自动生成的代码模板,LongClick是返回false。如果想自己触发,则需要手动改成true.

@Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        mItem_index=position;
        del_prj_ad.show();
        return true;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mItem_index=position;
        open_prj_ad.show();
    }

/*

*    好吧,后来发现即使长按,也没有弹出Dialog,很是奇怪啊,

*    仔细查看后发现是没有注册onItemLongClick,不好意思,但是应该还是有关系的,

*    要不然总会瞎onItemClick的。

*/

这里还有一个对Button或者ImageButton长按的说明,道理相似。

 

(七)org.json.JSONArray没有add方法

这个问题只有去访问该项目的github,不过看完之后还是会惊叹,果然是没有。它本身不打算考虑像ArrayList那样可以add到任意的index(虽然它内部的实现还是使用ArrayList),而通过put(Object o)方法就是将o放到内部List的尾部(直接List.add(o)),而put(index,o)是更改内部index位置的对象,不是想象的add(index,o)的实现。好了,想insert的想法是不能有的。

可以考虑新建对象,但是,开销太大了点,不值得。

(八)Java的泛型

使用泛型,确实是使用java的ArrayList<E>,但是知道这个(或者相似概念)要算是学习C++时涉及到的模板(template)。segmentF的讲解和排版都不错,是个入门的教程。提到的《java编程思想》也确实值得学习。这个的例子还是蛮多。

讲真,能想到用泛型的,估计都是手懒到一定程度了吧。我怎么想到用泛型了呢?不同的类型,却面对着相同的操作。即使是实现了相同的接口,却也无法将类型传递进去,承受着这种手忙脚乱的感觉,突然念叨了Python的好。

public JSONArray returnResult(ArrayList<IInterface> ii)
{
    JSONArray a=new JSONArray();
    for(IInterface i:ii)
    {
        a.put(i.toJson());//看着也可以呀,忘记了不行的写法了
    }
    return a;
}

(九)Activity与Fragment的生存周期

这个事情很烦躁啊,也可能是没认真研究的缘故。这里讲了动态与静态(即xml文件)处理frgment的问题,谁知道是不是坑呢。而这个研究的很细致了,将每一个过程(onCreate,onStart等等)说的很清楚,排版不错呦。

(十)Handler与Looper的机制

这里算是简介,而这里讲的非常透彻,当然在我还没弄清除之前还不能写太多评论。我的代码有些卡顿了。不知为何。慢慢的调试中。

int vol_id=0x01;
    int salt_id=0x02;
    int space_id=0x03;
    Handler mHandler=new Handler(new Handler.Callback(){
        @Override
        public boolean handleMessage(Message msg) {
            Log.i("E","xxxxxx"+ msg.what);
            if(msg.what==vol_id)
                if(vol_tv!=null)
                {
                    vol_tv.setText(vol_tv_text);
                }
            else if(msg.what==salt_id)
                if(salt_tv!=null)
                {
                    salt_tv.setText(salt_tv_text);
                }
            else if(msg.what==space_id)
                if(space_tv!=null)
                {
                    space_tv.setText(space_tv_text);
                }
            return false;
        }
    });

(十一)TextView中getBackground返回为null

网络上能搜索到的关于设置和获取TextView的代码很多,除了有关于考虑android版本情况的,其他的几乎是一致的。

然而自己的代码确实是总返回null,调试中可以看到mColor为空。在代码中,自己的空间是从xml布局中直接获取的,虽然在xml的父container中设置了backgroud,但是通过findViewById获得的还是努力了。最后不得不先尝试,即在findViewById之后手动调用setBackgroundColor,这样再次获取时就成功了。

Stack overflow中的这篇问题中的答案解析比较全面,但还是没说我的这种情况。

 

(十二)关于使用Sqlite作为本地存储的通用开头

自我感觉,这种方式的初始化应该会用得更多,所以记录下来,直接copy就可以了。其中包括了数据库路径优先外置存储器选择,适当改改也可以进行单利化。

public class PathDatabase extends SQLiteOpenHelper {
    public static int version=1;
    public static String db_name="name.db";
    String table_name="table";
    SQLiteDatabase mSQLiteDatabase;
    private PathDatabase(Context c,String full_db_name){
        super(c,full_db_name,null,PathDatabase.version);
    }
    public static PathDatabase getInstance(Context c){
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&Environment.isExternalStorageEmulated())
        {
            return new PathDatabase(c,Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+db_name);
        }else {
            return new PathDatabase(c,db_name);
        }
    }

关于sqlite获得id的问题,insert方法确实可以获得插入数据的rowid,文档上就这么写的。

public long insert (String table, String nullColumnHack, ContentValues values)

Added in API level 1

Convenience method for inserting a row into the database.

Parameters

table the table to insert the row into
nullColumnHack optional; may be null. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided values is empty, no column names are known and an empty row can't be inserted. If not set to null, the nullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where your values is empty.
values this map contains the initial column values for the row. The keys should be the column names and the values the column values

Returns

  • the row ID of the newly inserted row, or -1 if an error occurred

但是呢,又有提出,使用rowid作为主键是很不安全的,因为rowid会更改,做法就是

If you don’t want to read the whole post then just do this: Everytime you create a table with sqlite make sure to have an INTEGER PRIMARY KEY AUTOINCREMENT column (the rowid column will be an alias to this one).

所以我考虑就这么定义吧,但愿insert的时候返回的是这货。

(十三)onBackPressed

对于现如今的系统,Activity中有处理按返回键的事件,public void onBackPressed(),当然自动生成的会有super方法,也就会触发退出事件,一般会直接改掉。这个是具体的介绍,而这个介绍了双击退出键退出程序的写法,无非就是用时间差,简单而高效有用。我还想到用2秒自毁线程,然后在主线程中判断是否运行,实际上会挺犯不上的。

Simple is better than complex
public class Common {
    public static long last_time_click=-1;
    public static int backclick_internal=2;
}

@Override
    public void onBackPressed() {
        if((System.currentTimeMillis()-Common.last_time_click)<Common.backclick_internal){
            finish();
            System.exit(0);
        }else{
            Common.last_time_click=System.currentTimeMillis();
        }
    }

(十四)动态更改View的宽度等

动态更改是通过LinearLayout.LayoutParams来更改,调用View.setLayoutParams,比如这里说的清楚。但是遇到两个事情:java.lang.ClassCastException和宽度问题。

CastException问题是在给View的时候,但是这里的param应该是其父容器的类型,即在转换的时候(View.getLayoutParam获取的是ViewGroup.LayoutParams对象,需要强制转换)给出正确的类型。这里说明了一下,确实很准确。

RelativeLayout.LayoutParams mLayoutParams;
 public void onClick(View v) {
            mLayoutParams=(RelativeLayout.LayoutParams)mView.getLayoutParams();
            if(mImageButton1.isSelected()){
                mImageButton1.setSelected(false);
                mLayoutParams.width= Util.dip2px(Util.change_map_type_short_width);
            }else{
                mImageButton1.setSelected(true);
                mLayoutParams.width=Util.dip2px(Util.change_map_type_long_width);
            }
            mView.setLayoutParams(mLayoutParams);
}

宽度是因为在代码中赋值给width是像素值,而多数情况下是dip的数值,这需要进行转换计算。这里给了代码,但是感觉通用性不强,于是自己改造了Application类,见(十五)。通过静态方法,将计算的scale值放在第一次运行时计算。

public class Util {
    public static int px2dip(float pxValue) {
        return (int) (pxValue / MyApplication.scale + 0.5f);
    }
    public static int dip2px(float dpValue) {

        return (int) (dpValue * MyApplication.scale+0.5f);
    }
}

 

(十五)全局获取Context对象

这种方式是最为方便的,虽然没有顾忌太多的。这里是博客,下面是根据自己需要改造后配合上面计算像素与dip转换。

public class MyApplication extends Application {
    private  static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context=getApplicationContext();
        scale=context.getResources().getDisplayMetrics().density;
    }

    public static Context getContext() {
        return context;
    }
    public static float scale ;
}

(十六)振动器

通过服务获取即可,唯一的就是几个参数:一个是使用一个毫秒数来震动多久,另一个是两个参数,前一个是long数组,两两结合表示停顿时间,震动时间,第二个参数表示循环起始下标,如果使用-1则表示震动一次。具体的参看这里或者这里。代码抄至后者。

vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(2000);//震动指定时间 ,数据类型long,单位为毫秒,一毫秒为1/1000秒
vibrator.vibrate(new long[]{100,10,100,1000}, -1);//按照指定的模式去震动。
vibrator.cancel();//取消震动,立即停止震动。震动为一直震动的话,如果不取消震动,就算退出,也会一直震动

(十七)int类型的List

这个很基础,只可惜没注意过,或者没有学过。应为List以及ArrayList中只能存放继承至Object的对象,对于值类型不支持,但是可以使用其封装为Object的Integer以及类似的对象,比如这里说明的意思。

 

(十八)准确获取储存卡的路径

原本我使用的方法是下面。

public static Database getInstance(Context c){
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&Environment.isExternalStorageEmulated())
        {
            return new PathDatabase(c,Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+db_name);
        }else {
            return new Database(c,db_name);
        }
    }

但是发现,储存卡与sdcard的关系不一定,有可能是sdcard1才是储存卡所以需要一个准确的获取方法。

这里讲的非常全面。之前一直使用其他写法。原理以后可以详看(主要是Java的反射机制),下面代码就抄过来了。这个写的也不错,但是内容也差不多,做补充。

    import java.lang.reflect.Method;  
    import android.os.storage.StorageManager;  
      
        // 获取主存储卡路径  
        public String getPrimaryStoragePath() {  
            try {  
                StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);  
                Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null);  
                String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null);  
                // first element in paths[] is primary storage path  
                return paths[0];  
            } catch (Exception e) {  
                Log.e(TAG, "getPrimaryStoragePath() failed", e);  
            }  
            return null;  
        }  
          
        // 获取次存储卡路径,一般就是外置 TF 卡了. 不过也有可能是 USB OTG 设备...  
        // 其实只要判断第二章卡在挂载状态,就可以用了.  
        public String getSecondaryStoragePath() {  
            try {  
                StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);  
                Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null);  
                String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null);  
                // second element in paths[] is secondary storage path  
                return paths.length <= 1 ? null : paths[1];  
            } catch (Exception e) {  
                Log.e(TAG, "getSecondaryStoragePath() failed", e);  
            }  
            return null;  
        }  
          
        // 获取存储卡的挂载状态. path 参数传入上两个方法得到的路径  
        public String getStorageState(String path) {  
            try {  
                StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);  
                Method getVolumeStateMethod = StorageManager.class.getMethod("getVolumeState", new Class[] {String.class});  
                String state = (String) getVolumeStateMethod.invoke(sm, path);  
                return state;  
            } catch (Exception e) {  
                Log.e(TAG, "getStorageState() failed", e);  
            }  
            return null;  
        }  

 

 

博客

Hongyang

guolin

© 著作权归作者所有

共有 人打赏支持
Ev4n
粉丝 5
博文 27
码字总数 14699
作品 0
成都
私信 提问
【android学习之十五】——多媒体2:相机Camera

二、多媒体之相机Camera 手机的相机功能是当前大家玩拍照的一个必备功能,本篇的学习,我认为网上的一篇博文的讲解更容易理解一下,这里就转一下博文,自己把自己遇到的的问题给补充进来。引...

晨曦之光
2012/03/08
4.1K
1
最新 Android 恶意软件可远程控制用户手机

安全研究人员发现一款最新针对Android操作系统的恶意软件,黑客可通过该软件远程控制用户手机,并在用户毫不知情的情况下在其手机上安装未经许可的软件。首席工程师与移动安全专家蒂姆·怀亚...

虫虫
2012/04/08
641
1
【Android游戏开发之一】设置全屏以及绘画简单的图形

李华明Himi 原创,转载务必在明显处注明: 转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/263.html 很多童鞋说我的代码运行后,点击home或者back后会程序异常,...

迷途d书童
2012/03/19
0
0
Android Wear开发系列教程——搭建开发环境

前言 很久没有写博客了,伴随着谷歌发布新的Android Wear开发平台,笔者还是决定写点东西了。在接下来的一段时间里,我将跟大家一起去研究这个会被穿在身上的系统。俗话说,工欲善其事必先利...

多利的猫粮
2014/09/23
0
5
Google暑期大学生博客分享大赛开赛

2010 年,首届 Google 暑期大学生博客分享大赛开赛啦——今年的主题是 Android! 立即报名 Android 是 Google 2007 年推出的基于 Linux 的开源手机操作系统。我们相信 Android 的未来关键取决...

红薯
2010/07/18
574
1

没有更多内容

加载失败,请刷新页面

加载更多

Netty 备录 (一)

入职新公司不久,修修补补1个月的bug,来了点实战性的技术---基于netty即时通信 还好之前对socket有所使用及了解,入手netty应该不是很难吧,好吧,的确有点难,刚看这玩意的时候,可能都不知道哪里...

_大侠__
昨天
4
0
Django简单介绍和用户访问流程

Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。 Django是一个开放源代码的Web应用框架,由Python写成。 Django遵守BSD版权,初...

枫叶云
昨天
7
0
EOS错误代码及中文释义

本文集汇总了EOS区块链常见错误代码及其含义,完整错误代码集请查看 EOS错误代码集 - 汇智网 EOS错误代码列表如下, <table class="table table-striped"> <thead> <tr><th>错误代码</th><t......

汇智网教程
昨天
2
0
Spring Cloud Stream消费失败后的处理策略(四):重新入队(RabbitMQ)

应用场景 之前我们已经通过《Spring Cloud Stream消费失败后的处理策略(一):自动重试》一文介绍了Spring Cloud Stream默认的消息重试功能。本文将介绍RabbitMQ的binder提供的另外一种重试...

程序猿DD
昨天
4
0
kiss原则

KISS 原则是用户体验的高层境界,简单地理解这句话,就是要把一个产品做得连白痴都会用,因而也被称为“懒人原则”。换句话说来,”简单就是美“。KISS 原则源于 David Mamet(大卫马梅)的电...

NB-One
昨天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部