Sqlite中增加字段的语法和其他的数据库一样使用Alter关键字,具体例子如下:
1 |
ALTER TABLE tablename ADD COLUMN fieldname NUMERIC DEFAULT 0 |
但是要注意的是,sqlite中不支持一次增加多列,所以如果你要增加多列的话就要执行多次alter table语句
Sqlite中增加字段的语法和其他的数据库一样使用Alter关键字,具体例子如下:
1 |
ALTER TABLE tablename ADD COLUMN fieldname NUMERIC DEFAULT 0 |
但是要注意的是,sqlite中不支持一次增加多列,所以如果你要增加多列的话就要执行多次alter table语句
1、运行时授权
6.0以后用户可以运行时对应用进行授权管理,当你的应用需要使用某个权限时可以用checkSelfPermission()检查是否拥有某个权限,如果没有这个权限的话使用requestPermissions()来申请权限。
2、磕睡模式和应用空闲状态的优化
此特性是为了更好的节省系统用电量。
3、除去Appche Http Client的支持
如果你原来使用了这个Client,并且你的目标系统在Android2.3(Api Level9)以上,那么你现在可以使用HttpURLConnection代码Apache http client,这个api的流压缩和响应缓存可以提高网络访问的效率,并降低电量的耗损。如果你还想继续使用Apache http client,那么你可以在build.gradle中加入以下代码
1 2 3 |
android { useLibrary 'org.apache.http.legacy' } |
4、BoringSSL
使用BoringSSl代替原来的OpenSSL,使用NDK的需要注意,具体查一下官网的介绍。
5、硬件标识访问
为了更好的保护用户的数据,此版本不再支持程序获取设备的本地Wifi和蓝牙的硬件标识,WifiInfo.getMACAddress()和BluetoothAdapter.getAddress()方法将始终返回值为02:00:00:00:00:00
如果要通过蓝牙或者Wifi扫描获取附近的外部设备的硬件标识,你的应用必须定义ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION权限。
6、通知Notifications
不在支持方法Notification.setLatestEventInfo(),使用Notification.Builder类代替来创建notifications。如果要多次更新notification,定义一个全局的Notification.Builder实例并在这个对象内更新,最后使用build()方法获取更新后的notification对象。
7、AudioManager的改变
不再支持直接通过AudioManager类设置音量和静音指定的音频流。setStreamSolo()方法不再推荐使用,你可以通过requestAudioFocus()方法代替。setStreamMute()也不再推荐使用,你可以使用adjustStreamVolume()方法和参数ADJUST_MUTE or ADJUST_UNMUTE代替该方法。
8、文本的选择操作
在此版本中,用户选择文本后,你可以顶部的ActionBar中显示对选择文本的复制、粘贴、剪切等按钮,具体的参考官网中提供的步骤。
9、浏览器书签的变化
不在支持全局的书签,应用不再支持获取和保存浏览器中的书签。android.provider.Browser.getAllBookmarks() 和 android.provider.Browser.saveBookmark() 方法被移除,同样地,READ_HISTORY_BOOKMARKS和 WRITE_HISTORY_BOOKMARKS 权限被移除。
10、Android Keystore的变化
Android Keystore Provider不再支持DSA,ECDSA还在支持,没用过此功能,不知道有什么影响。
11、WIFI和网络的变化
1.首先要有一个Long型的主键
2.该主键的初始值要赋值为null
如下:
1 2 3 4 5 6 |
@Entity(nameInDb = "tags") public class TagBean { @Property(nameInDb = "id") @Id(autoincrement = true) private Long id = null; } |
原理是:
当id的初始值设为null时,执行insert into 语句时,id的值也为null,然后数据库系统会自己计算这个,如下这个sql语句
1 |
insert into tags(id, uniqid, tagname, deleted) values(null, '1bb61dad-ef47-45c6-a1a8-905cd7f7f2f1', '汽车2331', 0) |
可以通过以下几种方法实现EditText的只读属性
1. 方法一:使用EditText的android:Editable属性
将EditText的Editable属性设置为false后,EditText就成只读了,缺点是不能在java代码中动态设置,而且这个属性android官方已经不推荐使用了,官方的解释是要想一个view可编辑(Editable=true)可以用EditText,不可编辑用TextView就可以了 8-O
2. 方法二:使用TextView替代
既然TextView和EditText就差一个可编辑,那么用一个TextView去替代EditText好了。只读的时候显示TextView隐藏EditText,编辑的时候显示EditText隐藏TextView,不过TextView必须和EditText用同样的样式,以不让用户查觉到组件变换了。本人没亲测这种方法,大家有兴趣的话可以试试。
3. 方法三:设置EditText的keylistener来实现
代码不多,直接把完整的代码贴出来吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package com.bcoder.study.edittextapp; import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.method.KeyListener; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { EditText edt1; KeyListener storedKeylistener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edt1 = (EditText) findViewById(R.id.editText); // 保存默认的KeyListener以便恢复 storedKeylistener = edt1.getKeyListener(); } public void setReadOnly(View v){ // 设置KeyListener为null, 变为不可输入状态 edt1.setKeyListener(null); // 如果需要,设置文字可选 edt1.setTextIsSelectable(true); } public void setEditable(View v){ // 可编辑时弹出软键盘 final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(edt1, 0); // 恢复KeyListener edt1.setKeyListener(storedKeylistener); // 如果需要,设置文字可选 edt1.setTextIsSelectable(true); // 恢复KeyListener后,键盘不会自动弹出,要通过代码弹出 edt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { imm.showSoftInput(edt1, 0); } }); // 将光标定位到最后 edt1.setSelection(edt1.getText().length()); } } |
布局文件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.bcoder.study.edittextapp.MainActivity"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/editText" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:singleLine="false" android:lines="5" android:text="http://svn1.bcoder.com" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Readonly" android:id="@+id/button" android:layout_below="@+id/editText" android:layout_centerHorizontal="true" android:layout_marginTop="74dp" android:onClick="setReadOnly" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Editable" android:id="@+id/button2" android:layout_below="@+id/button" android:layout_centerHorizontal="true" android:onClick="setEditable" /> </RelativeLayout> |
Java、Php等语言中都有成熟的框架来解析Json数据,可以让我们使用很少的代码就把格式化好的json数据转换成程序可识别的对象或者属性,同时delphi中也有这样的组件来实现此功能,即IsuperObject。如果还没有这个组件的请在网上搜索下载或者在下面留言处留下你的邮箱向本人索取。
下面先说一下ISuperObject中几个常用的函数
下面我们看一个演示代码,json数据如下
1 2 3 4 5 |
{ "retcode": "1", "datafrom": "server", "users": "[{\"id\":1, \"username\": \"liuderu\", \"website\": \"bcoder.com\"},{\"id\":2, \"username\": \"Jeoe\", \"website\": \"baidu.com\"}]" } |
Delphi版本2010,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
unit uFmMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Buttons, superobject; type TFmMain = class(TForm) Memo1: TMemo; ListView1: TListView; BitBtn1: TBitBtn; Label1: TLabel; procedure BitBtn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var FmMain: TFmMain; implementation {$R *.dfm} procedure TFmMain.BitBtn1Click(Sender: TObject); var jRet, jUsers: ISuperObject; aryUsers: TSuperArray; retCode: integer; strUsers: string; i: integer; begin jRet := SO(Memo1.Text); if (jRet.O['retcode'] <> nil) then begin retCode := jRet.O['retcode'].AsInteger; Label1.Caption := '返回值:' + IntToStr(retCode) + '; 数据来源:' + jRet.O['datafrom'].AsString; if(jRet.O['retcode'].AsInteger = 1) then begin strUsers := jRet.O['users'].AsString; jUsers := SO(strUsers); aryUsers := jUsers.AsArray; for I := 0 to aryUsers.Length - 1 do begin with ListView1.Items.Add do begin Caption := aryUsers[i].O['id'].AsString; SubItems.Add(aryUsers[i].O['username'].AsString); SubItems.Add(aryUsers[i].O['website'].AsString); end; end; end; end; end; end. |
在Android的sdk/tools/proguard/docs/index.html
比如:
file:///home/liuderu/software/adt-bundle-linux-x86_64-20131030/sdk/tools/proguard/docs/index.html
当continue遇上finally,continue执行后仍会执行finally中的代码,如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void main(String[] args){ for(int i = 1; i < 11; i++){ try{ if(i % 5 == 0){ System.out.println("continue: i = " + i); continue; } } finally { System.out.println("finally: i = " + i); } } } |
运行输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 |
finally: i = 1 finally: i = 2 finally: i = 3 finally: i = 4 continue: i = 5 finally: i = 5 finally: i = 6 finally: i = 7 finally: i = 8 finally: i = 9 continue: i = 10 finally: i = 10 |
我们知道mailto链接可以指定发送邮件到某个邮箱,但是mailto其实还支持其他的参数,这些参数在做后台客服网站是还是很有用的。
mailto的参数格式和url中的参数格式是一样的,参数段以?开头,不同的参数间以&分隔,如<a href=”mailto:test@bcoer.com?subject=mysubject”>TEST</a>
mailto支持以下参数:
如下面的例子所示:
1 |
<a href="mailto:test@bcoer.com?cc=test1@163.com&bcc=test2@qq.com&subject=mysubject&body=this is an email from bcoder.com">TEST</a> |
点击链接TEST后,系统就会自动打开邮件发送程序,并在相应的栏目中填入链接中的数据,如果我们的后台系统需要给客户发送反馈邮件,这样做就可以省去很多不必要的文字输入了。
一共有三种方法可以实现StringBuilder的清空
下面通过代码验证三种方法的效率
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public class StringBuilderClearTest { public static void main(String[] args){ long time = System.currentTimeMillis(); System.out.println("begin: " + time); StringBuilder sbMain1 = new StringBuilder(); StringBuilder sbMain2 = new StringBuilder(); StringBuilder sbMain3 = new StringBuilder(); StringBuilder sb1 = null; for(int i=0; i<1000000; i++){ sb1 = new StringBuilder("a1"); sb1.append("a2"); sb1.append("a3"); sbMain1.append(sb1); } long time1 = System.currentTimeMillis(); StringBuilder sb2 = new StringBuilder(); for(int i=0; i<1000000; i++){ sb2.delete(0, sb2.length()); sb2.append("b1"); sb2.append("b2"); sb2.append("b3"); sbMain2.append(sb2); } long time2 = System.currentTimeMillis(); StringBuilder sb3 = new StringBuilder(); for(int i=0; i< 1000000; i++){ sb3.setLength(0); sb3.append("c1"); sb3.append("c2"); sb3.append("c3"); sbMain3.append(sb3); } long time3 = System.currentTimeMillis(); System.out.println(sbMain1.length()); System.out.println(sbMain2.length()); System.out.println(sbMain3.length()); System.out.println("New耗时: " + (time1 - time)); System.out.println("delete耗时: " + (time2 - time1)); System.out.println("setLength: " + (time3 - time2)); } } |
测试了十几次,选了一次比较有代表性的结果:
1 2 3 |
New耗时 90 delete耗时: 73 setLength: 63 |
由结果可见setLength是最快的,delete不相上下,new是最慢的