Android Ndk(Beginner ‘s guide)(3.4)

从原生代码里面抛出异常

Store项目里面的异常处理还不是太令人满意。如果请求的值不能被发现,或者取得的值的类型与请求值的类型不同,就会返回一个默认的值。我们当然需要一个方法来处理发生的错误。那么更好的处理一个错误而不是一个意外?

行动时间——在Store里面产生异常

首先在Java方面产生和捕获异常:
1、在com.packtpub.exception里面创建一个继承Exception的InvalidTypeException类
public class InvalidTypeException extends Exception {
public InvalidTypeException(String pDetailMessage) {
super(pDetailMessage);
}
}
2、重复上面的操作创建继承Exception的NotExistingKeyException和继承RuntimeException的StoreFullException
3、打开Store.java,在获得原型部分声明抛出异常(StoreFullException是一个RuntimeException不需要进行声明):
public class Store {
static {
System.loadLibrary(“store”);
}
public native int getInteger(String pKey)
throws NotExistingKeyException, InvalidTypeException;
public native void setInteger(String pKey, int pInt);
public native String getString(String pKey)
throws NotExistingKeyException, InvalidTypeException;
public native void setString(String pKey, String pString);
public native Color getColor(String pKey)
throws NotExistingKeyException, InvalidTypeException;
public native void setColor(String pKey, Color pColor);
}
4、异常需要捕获,在onGetValue()里面实现NotExistingKeyException和InvalidTypeException。在onSetValue()里面不过StoreFullException以防数据不能插入:
public class StoreActivity extends Activity {
...
private void onGetValue() {
String lKey = mUIKeyEdit.getText().toString();
StoreType lType = (StoreType) mUITypeSpinner
.getSelectedItem();
try {
switch (lType) {
...
}
}
catch (NotExistingKeyException eNotExistingKeyException) {
displayError(“Key does not exist in store”);
} catch (InvalidTypeException eInvalidTypeException) {
displayError(“Incorrect type.”);
}
}

private void onSetValue() {
String lKey = mUIKeyEdit.getText().toString();
String lValue = mUIValueEdit.getText().toString();
StoreType lType = (StoreType) mUITypeSpinner
.getSelectedItem();
try {
switch (lType) {
...
}
}
catch (NumberFormatException eNumberFormatException) {
displayError(“Incorrect value.”);
} catch (IllegalArgumentException eIllegalArgumentException) 
{
displayError(“Incorrect value.”);
} catch (StoreFullException eStoreFullException) {
displayError(“Store is full.”);
}
}
...
}

5.打开前面创建的jni/Store.h文件,新建三个新的帮助函数来抛出异常:
#ifndef _STORE_H_
#define _STORE_H_
...
void throwInvalidTypeException(JNIEnv* pEnv);
void throwNotExistingKeyException(JNIEnv* pEnv);
void throwStoreFullException(JNIEnv* pEnv);
#endif
6.NotExistingKeyException和InvalidTypeException仅仅只有在从Store获取值的时候才抛出异常。一个好的地方来抛出异常就是在检查输入的时候isEntryValid().打开jni/Store.c按照下面修改:
#include “Store.h”
#include <string.h>
int32_t isEntryValid(JNIEnv* pEnv, StoreEntry* pEntry,
StoreType pType) {
if (pEntry == NULL) {
throwNotExistingKeyException(pEnv);
} else if (pEntry->mType != pType) {
throwInvalidTypeException(pEnv);
} else {
return 1;
}
return 0;
}
...
7.StoreFullException明显就是在插入一个值的时候产生的。修改相同文件下面的allocateEntry()函数:
...
StoreEntry* allocateEntry(JNIEnv* pEnv, Store* pStore, jstring 
pKey){
StoreEntry* lEntry = findEntry(pEnv, pStore, pKey);
if (lEntry != NULL) {
releaseEntryValue(pEnv, lEntry);
} else {
if (pStore->mLength >= STORE_MAX_CAPACITY) {
throwStoreFullException(pEnv);
return NULL;
}
// Initializes and insert the new entry.
...
}
return lEntry;
}
...
8.我们必须实现throwNOtExistingException()方法。为了扔出一个java异常我们首先要做的是找到相关的类。在JNI里面java类的引用是由jclass代替的。然后通过ThrowNew()来抛出异常。一旦我们不再需要异常类的引用,我们可以使用DeleteLocalRef()来删除:
...
void throwNotExistingKeyException(JNIEnv* pEnv) {
jclass lClass = (*pEnv)->FindClass(pEnv,
“com/packtpub/exception/NotExistingKeyException”);
if (lClass != NULL) {
(*pEnv)->ThrowNew(pEnv, lClass, “Key does not exist.”);
}
(*pEnv)->DeleteLocalRef(pEnv, lClass);
}
9.重复以上步骤完成其他两个异常。代码是完全相同的(即使是抛出一个运行中的异常),仅仅需要改名类名。

以上我们完成了什么?

运行程序然后试着来获取不存在的值。重复前面的操作取回在Store里面存在但是是不同类型的值,在GUI里面选择类型。在两种情况下,都会有异常抛出。如果你在store里面试着保存超过16个引用也同样会有错误提示。
抛出异常并不是一项复杂的任务,并且,他是JNI引用的好的java回调机制。一个异常是实例化jclass类型的描述。根据他的完整名字,类描述符可以在当前目录下被找到。(就是包名路径)
一旦产生异常,就不要继续调用JNI,应该处理异常。原生代码应该处理完异常,然后给Java反馈。当然也有可能在没有java代码运行的时候一直由原生代码执行下去。当原生代码返回的时候,异常就会由VM传递到java。
我们删除了一个本地引用,因为在使用之后我们就不在需要他了(8的一步)。当JNI传给你什么东西,不要忘记回传给他。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值