当前位置:  编程技术>移动开发
本页文章导读:
    ▪contentprovider的学习范例        contentprovider的学习实例 一、ContentProvider简介       当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共.........
    ▪ ExpandableListView的施用        ExpandableListView的运用 android中有一种expandablelistview,可以扩展的listview,就是那种点击一下可以扩展出子项,再点一下收缩回去的显示list。 因为需要查看一堆文件的目录结构,就使用了expandab.........
    ▪ java 运行时错误       java 运行时异常 Java提供了两类主要的异常:runtime exception和checked exception。checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常。对于这种异常,JAVA编译器强制要求我们必需.........

[1]contentprovider的学习范例
    来源: 互联网  发布时间: 2014-02-18
contentprovider的学习实例

一、ContentProvider简介
       当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
二、Uri类简介
       Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

       1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
       2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
       3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
•         要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
•         要操作contact表中id为10的记录的name字段, contact/10/name
•         要操作contact表中的所有记录,可以构建这样的路径:/contact
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
三、UriMatcher、ContentUrist和ContentResolver简介
       因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。

       UriMatcher:用于匹配Uri,它的用法如下:
       1.首先把你需要匹配Uri路径全部给注册上,如下:
       //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
       UriMatcher  uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
       //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
       uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
       //如果match()方法匹配   content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
       uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符
      
       2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。

       ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
•         withAppendedId(uri, id)用于为路径加上ID部分
•         parseId(uri)方法用于从路径中获取ID部分

       ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。
四、ContentProvider示例程序
Manifest.xml中的代码:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<application android:icon="@drawable/icon" android:label="@string/app_name">

                <activity android:name=".TestWebviewDemo" android:label="@string/app_name">

                        <intent-filter>

                                <action android:name="android.intent.action.MAIN" />

                                <category android:name="android.intent.category.LAUNCHER" />

                        </intent-filter>

                        <intent-filter>

                                <data android:mimeType="vnd.android.cursor.dir/vnd.ruixin.login" />

                        </intent-filter>

                        <intent-filter>

                                <data android:mimeType="vnd.android.cursor.item/vnd.ruixin.login" />

                        </intent-filter>

                          

                </activity>

                <provider android:name="MyProvider" android:authorities="com.ruixin.login" />

        </application>

需要在<application></application>中为provider进行注册!!!!
首先定义一个数据库的工具类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public class RuiXin {

  

        public static final String DBNAME = "ruixinonlinedb"; 

        public static final String TNAME = "ruixinonline";

        public static final int VERSION = 3;

          

        public static String TID = "tid";

        public static final String EMAIL = "email";

        public static final String USERNAME = "username";

        public static final String DATE = "date";

        public static final String SEX = "sex";

          

          

        public static final String AUTOHORITY = "com.ruixin.login";

        public static final int ITEM = 1;

        public static final int ITEM_ID = 2;

          

        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.ruixin.login";

        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.ruixin.login";

          

        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTOHORITY + "/ruixinonline");

}

 

·                                                 然后创建一个数据库:

?

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

public class DBlite extends SQLiteOpenHelper {

        public DBlite(Context context) {

                super(context, RuiXin.DBNAME, null, RuiXin.VERSION);

                // TODO Auto-generated constructor stub

        }

        @Override

        public void onCreate(SQLiteDatabase db) {

                // TODO Auto-generated method stub

                        db.execSQL("create table "+RuiXin.TNAME+"(" +

                                RuiXin.TID+" integer primary key autoincrement not null,"+

                                RuiXin.EMAIL+" text not null," +

                                RuiXin.USERNAME+" text not null," +

                                RuiXin.DATE+" interger not null,"+

                                RuiXin.SEX+" text not null);");

        }

        @Override

        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

                // TODO Auto-generated method stub

        }

        public void add(String email,String username,String date,String sex){

                SQLiteDatabase db = getWritableDatabase();

                ContentValues values = new ContentValues();

                values.put(RuiXin.EMAIL, email);

                values.put(RuiXin.USERNAME, username);

                values.put(RuiXin.DATE, date);

                values.put(RuiXin.SEX, sex);

                db.insert(RuiXin.TNAME,"",values);

        }

}

·                                                 接着创建一个Myprovider.java对数据库的接口进行包装:

?

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

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

public class MyProvider extends ContentProvider{

  

        DBlite dBlite;

        SQLiteDatabase db;

          

        private static final UriMatcher sMatcher;

        static{

                sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

                sMatcher.addURI(RuiXin.AUTOHORITY,RuiXin.TNAME, RuiXin.ITEM);

                sMatcher.addURI(RuiXin.AUTOHORITY, RuiXin.TNAME+"/#", RuiXin.ITEM_ID);

  

        }

        @Override

        public int delete(Uri uri, String selection, String[] selectionArgs) {

                // TODO Auto-generated method stub

                db = dBlite.getWritableDatabase();

                int count = 0;

                switch (sMatcher.match(uri)) {

                case RuiXin.ITEM:

                        count = db.delete(RuiXin.TNAME,selection, selectionArgs);

                        break;

                case RuiXin.ITEM_ID:

                        String id = uri.getPathSegments().get(1);

                        count = db.delete(RuiXin.TID, RuiXin.TID+"="+id+(!TextUtils.isEmpty(RuiXin.TID="?")?"AND("+selection+')':""), selectionArgs);

                    break;

                default:

                        throw new IllegalArgumentException("Unknown URI"+uri);

                }

                getContext().getContentResolver().notifyChange(uri, null);

                return count;

        }

  

        @Override

        public String getType(Uri uri) {

                // TODO Auto-generated method stub

                switch (sMatcher.match(uri)) {

                case RuiXin.ITEM:

                        return RuiXin.CONTENT_TYPE;

                case RuiXin.ITEM_ID:

                    return RuiXin.CONTENT_ITEM_TYPE;

                default:

                        throw new IllegalArgumentException("Unknown URI"+uri);

                }

        }

  

        @Override

        public Uri insert(Uri uri, ContentValues values) {

                // TODO Auto-generated method stub

                  

                db = dBlite.getWritableDatabase();

                long rowId;

                if(sMatcher.match(uri)!=RuiXin.ITEM){

                        throw new IllegalArgumentException("Unknown URI"+uri);

                }

                rowId = db.insert(RuiXin.TNAME,RuiXin.TID,values);

                   if(rowId>0){

                           Uri noteUri=ContentUris.withAppendedId(RuiXin.CONTENT_URI, rowId);

                           getContext().getContentResolver().notifyChange(noteUri, null);

                           return noteUri;

                   }

                   throw new IllegalArgumentException("Unknown URI"+uri);

        }

  

        @Override

        public boolean onCreate() {

                // TODO Auto-generated method stub

                this.dBlite = new DBlite(this.getContext());

//                db = dBlite.getWritableDatabase();

//                return (db == null)?false:true;

                return true;

        }

  

        @Override

        public Cursor query(Uri uri, String[] projection, String selection,

                        String[] selectionArgs, String sortOrder) {

                // TODO Auto-generated method stub

                db = dBlite.getWritableDatabase();                

                Cursor c;

                Log.d("-------", String.valueOf(sMatcher.match(uri)));

                switch (sMatcher.match(uri)) {

                case RuiXin.ITEM:

                        c = db.query(RuiXin.TNAME, projection, selection, selectionArgs, null, null, null);

                  

                        break;

                case RuiXin.ITEM_ID:

                        String id = uri.getPathSegments().get(1);

                        c = db.query(RuiXin.TNAME, projection, RuiXin.TID+"="+id+(!TextUtils.isEmpty(selection)?"AND("+selection+')':""),selectionArgs, null, null, sortOrder);

                    break;

                default:

                        Log.d("!!!!!!", "Unknown URI"+uri);

                        throw new IllegalArgumentException("Unknown URI"+uri);

                }

                c.setNotificationUri(getContext().getContentResolver(), uri);

                return c;

        }

        @Override

        public int update(Uri uri, ContentValues values, String selection,

                        String[] selectionArgs) {

                // TODO Auto-generated method stub

                return 0;

        }

}



最后创建测试类:

?

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

public class Test extends Activity {

    /** Called when the activity is first created. */

   private DBlite dBlite1 = new DBlite(this);;

        private ContentResolver contentResolver;

                    public void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                setContentView(R.layout.main);

                //先对数据库进行添加数据

            dBlite1.add(email,username,date,sex);

            //通过contentResolver进行查找

             contentResolver = TestWebviewDemo.this.getContentResolver();

            Cursor cursor = contentResolver.query(

                  RuiXin.CONTENT_URI, new String[] {

                  RuiXin.EMAIL, RuiXin.USERNAME,

                  RuiXin.DATE,RuiXin.SEX }, null, null, null);

                while (cursor.moveToNext()) {

                     Toast.makeText(

                    TestWebviewDemo.this,

                    cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL))

                            + " "

                            + cursor.getString(cursor.getColumnIndex(RuiXin.USERNAME))

                            + " "

                            + cursor.getString(cursor.getColumnIndex(RuiXin.DATE))

                            + " "

                            + cursor.getString(cursor.getColumnIndex(RuiXin.SEX)),

                           Toast.LENGTH_SHORT).show();

                     }

                   startManagingCursor(cursor);  //查找后关闭游标

            }

        }


注:上面是在一个程序中进行的测试,也可以再新建一个工程来模拟一个新的程序,然后将上面查询的代码加到新的程序当中!这样就模拟了contentprovider的数据共享功能了!
新建个工程:TestProvider
创建一个测试的activity

?

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

public class Test extends Activity {

    /** Called when the activity is first created. */

        private ContentResolver contentResolver;

                    public void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                setContentView(R.layout.main);

                

            //通过contentResolver进行查找

              contentResolver = TestWebviewDemo.this.getContentResolver();                     

             Cursor cursor = contentResolver.query(

                RuiXin.CONTENT_URI, new String[] {

                RuiXin.EMAIL, RuiXin.USERNAME,

                RuiXin.DATE,RuiXin.SEX }, null, null, null);

            while (cursor.moveToNext()) {

               Toast.makeText(TestWebviewDemo.this,

                       cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL))

                       + " "

                       + cursor.getString(cursor.getColumnIndex(RuiXin.USERNAME))

                       + " "

                       + cursor.getString(cursor.getColumnIndex(RuiXin.DATE))

                       + " "

                       + cursor.getString(cursor.getColumnIndex(RuiXin.SEX)),

                       Toast.LENGTH_SHORT).show();

                   }

                   startManagingCursor(cursor);  //查找后关闭游标

            }

        }

运行此程序就能实现共享数据查询了!

注:新建的程序中的manifest.xml中不需要对provider进行注册,直接运行就行,否则会报错!


    
[2] ExpandableListView的施用
    来源: 互联网  发布时间: 2014-02-18
ExpandableListView的运用

android中有一种expandablelistview,可以扩展的listview,就是那种点击一下可以扩展出子项,再点一下收缩回去的显示list。

因为需要查看一堆文件的目录结构,就使用了expandablelist以便于直观地看到结构形式。

根据APIDemos中的实例,进行细微的改动就可以够自己使用了。

自己建立的activity继承自ExpandableListActivity,设定好的是显示两级结构。至于知否能够扩展更多的级,还没有实验,准备实验一下。顶层是group,第二层是child。

顶层的结构定义为:List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();是个Arraylist结构,其中是Map键值对。

第二层的结构定义为: List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();这个可以看成是比顶层多出了个List,是在顶层list中的list,其中也是键值对,所以定义成list<list<map>>>。

之后就是要向每个键值对中写入数据,在list中显示。对于顶层:

Map<String, String> curGroupMap = new HashMap<String, String>();     //定义curGroupMap是Map结构,存储需要用到的键值对      

groupData.add(curGroupMap);            //添加到List中,map结构作为参数,现在list中的单元是map结构存储的数据,表示顶层的数据列表

curGroupMap.put(NAME, "Group " + i);//向map中写入键值对

对于第二层:

因为每个child也是list,所以要先为每个group下的child定义一个List,有多少个group项就应该有多少个如下的children项,这个在使用的时候要注意,否则会出现不同的child键值对覆盖等问题。

 List<Map<String, String>> children = new ArrayList<Map<String, String>>();//这个同顶层的类似,也可以看成,从这一步起又开始了刚才定义顶层是的步骤

for (int j = 0; j < 15; j++) {  

 Map<String, String> curChildMap = new HashMap<String, String>();              //参见以上group中的相关方法

 children.add(curChildMap);                

curChildMap.put(NAME, "Child " + j);              

}          

 childData.add(children);//最后将children这个list添加成为childData中的一个元素。一个child中可能会有好几项,children表示第二层的元素列表

再理清两层数据的具体层次关系后,通过SimpleExpandableListAdapter准备数据匹配器,

mAdapter = new SimpleExpandableListAdapter(              

this,//1.上下文              

groupData,//2.顶层数据列表              

android.R.layout.simple_expandable_list_item_1,//3.1层显示样式 ,系统自定义        

new String[] {ENTRY}, //4.顶层map的键,还可以有一个键        

new int[] { android.R.id.text1},// 5.顶层数据显示的View ID        ,系统自定义       

childData,               //原理同上

android.R.layout.simple_expandable_list_item_2,            

 new String[] {ENTRY},              

new int[] { android.R.id.text1}              

);

然后设定匹配器 setListAdapter(mAdapter)

最后程序的运行结果如下:

 



 

 首先看下布局文件:在定义布局时,这里要定义三个布局文件,全在res/layout目录下,我先把布局文件附在下面,具体有什么用,我在下面会详细说明

  main.xml:

  <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       >
    <ExpandableListView
        android:id="@id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:drawSelectorOnTop="false"/>
    <TextView 
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:id="@id/android:empty"
       android:text="No Data"/>
   </LinearLayout> 

  groups.xml:

  <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       >
    <TextView 
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:id="@+id/group"
       android:textSize="25sp"
       android:paddingLeft="35px"
       android:paddingTop="10px"
       android:paddingRight="5px"
       android:paddingBottom="10px"
       android:text="No Data"/>
   </LinearLayout>

  childs.xml:

  <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       >
    <TextView 
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:id="@+id/child"
       android:textSize="15sp"
       android:paddingLeft="25px"
       android:paddingTop="10px"
       android:paddingRight="5px"
       android:paddingBottom="10px"
       android:text="No Data"/>
   </LinearLayout>

  首先,第一个布局文件main.xml是在主界面定义一个ExpandableListView ,在这里我们就要和在做ListView是的方法做下对比了,其实这个listView的显示类似。主要是用来显示ExpandableListView 下的数据。第二个布局文件是定义ExpandableListView 下的一级条目目录。在这里我只为一级条目目录添加一个textView控件。第三个布局文件是定义ExpandableListView 下的二级条目目录,和一级条目目录一样,布局文件里也只有一个TextView控件。

  Java代码:

  ExpandableActivity:

  package cn.yj3g.ExpandableListActivity;
  
   import java.util.ArrayList;
   import java.util.HashMap;
   import java.util.List;
   import java.util.Map;
   import android.app.ExpandableListActivity;
   import android.os.Bundle;
   import android.view.View;
   import android.widget.ExpandableListView;
   import android.widget.SimpleExpandableListAdapter;
   /**
    * 继承ExpandableListActivity类
    */
   public class ExpandableActivity extends ExpandableListActivity {
       @Override
       public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.main);
           // 创建一级条目
           List<Map<String, String>> groups = new ArrayList<Map<String, String>>();
           //创建两个一级条目标题
           Map<String, String> group1 = new HashMap<String, String>();
           group1.put("group", "音乐");
           Map<String, String> group2 = new HashMap<String, String>();
           group2.put("group", "歌词");
           groups.add(group1);
           groups.add(group2);
           // 创建一级条目下的的二级条目
           List<Map<String, String>> child1 = new ArrayList<Map<String, String>>();
           //同样是在一级条目目录下创建两个对应的二级条目目录
           Map<String, String> childdata1 = new HashMap<String, String>();
           childdata1.put("child", "青花瓷");
           Map<String, String> childdata2 = new HashMap<String, String>();
           childdata2.put("child", "东风破");
           child1.add(childdata1);
           child1.add(childdata2);
           //同上
           List<Map<String, String>> child2 = new ArrayList<Map<String, String>>();
           Map<String, String> childdata3 = new HashMap<String, String>();
           childdata3.put("child", "青花瓷.lrc");
           Map<String, String> childdata4 = new HashMap<String, String>();
           childdata4.put("child", "东风破.lrc");
           child2.add(childdata3);
           child2.add(childdata4);
           // 将二级条目放在一个集合里,供显示时使用
           List<List<Map<String, String>>> childs = new ArrayList<List<Map<String, String>>>();
           childs.add(child1);
           childs.add(child2);
           /**
            * 使用SimpleExpandableListAdapter显示ExpandableListView
            * 参数1.上下文对象Context
            * 参数2.一级条目目录集合
            * 参数3.一级条目对应的布局文件
            * 参数4.fromto,就是map中的key,指定要显示的对象
            * 参数5.与参数4对应,指定要显示在groups中的id
            * 参数6.二级条目目录集合
            * 参数7.二级条目对应的布局文件
            * 参数8.fromto,就是map中的key,指定要显示的对象
            * 参数9.与参数8对应,指定要显示在childs中的id
            */
           SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(
                   this, groups, R.layout.groups, new String[] { "group" },
                   new int[] { R.id.group }, childs, R.layout.child,
                   new String[] { "child" }, new int[] { R.id.child });
           setListAdapter(adapter);
   
       }
       /**
        * 设置哪个二级目录被默认选中
        */
       @Override
       public boolean setSelectedChild(int groupPosition, int childPosition,
               boolean shouldExpandGroup) {
               //do something
           return super.setSelectedChild(groupPosition, childPosition,
                   shouldExpandGroup);
       }
       /**
        * 设置哪个一级目录被默认选中
        */
       @Override
       public void setSelectedGroup(int groupPosition) {
           //do something
           super.setSelectedGroup(groupPosition);
       }
       /**
        * 当二级条目被点击时响应
        */
       @Override
       public boolean onChildClick(ExpandableListView parent, View v,
               int groupPosition, int childPosition, long id) {
               //do something
           return super.onChildClick(parent, v, groupPosition, childPosition, id);
       }
 
   }

  上面在显示ExpandableListView 是用的是SimpleExpandableListAdapter ,这里要传的参数比较多,大家在用时别一看到参数多就头疼,没事的,看注释你就知道各个参数的意思了。下面的三个重写方法是在显示ExpandableListView 是调用的,具体的用法就要根据需求来确定了。

 

 

 


    
[3] java 运行时错误
    来源: 互联网  发布时间: 2014-02-18
java 运行时异常
Java提供了两类主要的异常:runtime exception和checked exception。checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。

但是另外一种异常:runtime exception,也称运行时异常,我们可以不处理。当出现这样的异常时,总是由虚拟机接管。比如:我们从来没有人去处理过NullPointerException异常,它就是运行时异常,并且这种异常还是最常见的异常之一。

以前一直没仔细想过出现运行时异常了系统会怎样工作,最近在一个模块排错时,才无意中发现了系统是如何处理运行时异常。出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往我们不对他处理罢了。

也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。如果程序的退出刚好是你期望的结果,那就万事OK了。

但最近我在项目却遇的问题,恰恰是这因为没有对运行时异常进行处理,而导致程序在运行一小段时间后就当了。事情是这样的,由于写程序时我对多线程的并发处理不太会,也就把一个模块写成了单线程的,由它来循环处理一个数据队列。但没想到队列里面的数据有一些与预期的格式不一样,处理这样的数据时,程序就抛出了运行时异常。由于没有对异常进行处理,这个异常也就抛到了Thread.run()。最后这个处理线程肯定是被终止了,队列里面的数据也就不会再有程序去处理了。这个结果显然不是我想要的,队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而,影响下面对正常数据的处理啊。

所以最后我在程序的循环处理模块,里面加了一个catch处理,来扑捉所有的异常,决不让这个处理线程退出,要知道我的所有数据还要依靠他来处理呢 (^_^ )。在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常,或者是通过对异常的处理显式的控制程序退出。

知道了虚拟机怎么处理运行时异常,也更进一步理解了Sping对Hibernate的封装了。由于Hibernate是和数据库打交道,所以总是要抛出一些乱七八糟的checked异常,平时我们根本不想catch这些异常。因为这些异常总是把代码弄的乱乱的,搞的到处都是try{} catch(){}块,并且常常加了catch块,也并不能把程序从异常中恢复过来(异常处理的目标之一就是为了把程序从异常中恢复出来)。为了通过编译器的检查,程序员被迫加上了catch块,往往这些catch并没有发挥他应有的作用,反而带来了很大的不便。所以Spring对Hibernate封装时就把Hibernate的异常进行了封装,全部封装成运行时异常了。也就是Spring来扑捉Hibernate抛出的异常,然后Spring把异常转换成Spring自己定义的运行时异常再抛出。这样我们在编码时使用Spring来调用Hibernate时,可以不用catch块来处理一些不必要的异常。当然你确实要是想处理,也可以通过添加cathc块去处理异常。不过这个时候,你的Catch就要扑捉运行时异常了,而不是一般的checked异常了。

    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3