Android JNI学习入门之使用C++链表结构存储数据

来源:互联网 发布:lol西门代练淘宝店 编辑:程序博客网 时间:2024/05/20 05:45
  学习NDK开发,一方面是掌握Java和C/C++互相调用,另一方面是掌握C/C++语言本身的基础;因此我觉得入门的最好方式就是使用C/C++构建数据结构,然后存储数据;这样既可以掌握一些C++语言本身的基础知识,又可以掌握一些Java和C/C++对象的互相调用的方法。  本次项目是在Android Studio中构建的。  首先,我新建一个Java类,
public class LinkList {    static {        System.loadLibrary("native-linklist");    }    public LinkList(){        init();    }    public native void  init();    public native void  add(int key,String value);    public native int size();    public native Node next();    public native void prenext();    public native boolean hasnext();    public native String get(int key);}

然后在cpp文件中新建和它对象的h文件

#include "jni.h"#include "list.h"#include <stdlib.h>#include <string>#ifndef JNIEXAMPLE_NATIVE_LINKLIST_H#define JNIEXAMPLE_NATIVE_LINKLIST_Hextern "C"{using namespace std;Node *startNode= nullptr,*endNode= nullptr,*nextNode= nullptr;int count=0;JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_init(JNIEnv *,jobject);JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_add(JNIEnv *,jobject,jint ,jstring);JNIEXPORT jint JNICALL Java_com_xuye_xy_socket_jni_LinkList_size(JNIEnv *,jobject);JNIEXPORT jobject JNICALL Java_com_xuye_xy_socket_jni_LinkList_next(JNIEnv *,jobject);JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_prenext(JNIEnv *,jobject);JNIEXPORT jboolean JNICALL Java_com_xuye_xy_socket_jni_LinkList_hasnext(JNIEnv *,jobject);JNIEXPORT jstring JNICALL Java_com_xuye_xy_socket_jni_LinkList_get(JNIEnv *,jobject,jint);jobject newNode(JNIEnv *env,int key, const char *value);};

这个是Node类如下:

#include "jni.h"#ifndef JNIEXAMPLE_LIST_H#define JNIEXAMPLE_LIST_Hextern  "C"{class Node{public:    Node *next,*pre;    Node(){        this->key=0;        this->value= nullptr;    };    Node(int key, const char* value){        this->key=key;        this->value=value;    };    ~Node(){};    int getkey(){        return this->key;    }    const char* getvalue(){        return this->value;    };    void set(int key, const char* value){        this->key=key;        this->value=value;    }private:    int key;    const char *value;};};#endif //JNIEXAMPLE_LIST_H

然后是实现:

#include"native-linklist.h"JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_init(JNIEnv *env,jobject thiz){    startNode=new Node();    endNode=new Node();    nextNode=new Node();    nextNode->next=startNode;    startNode->next=endNode;    startNode->pre= nullptr;    endNode->pre=startNode;    endNode->next= nullptr;}JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_add(JNIEnv *env,jobject thiz,jint jst,jstring obj){    count++;    int key=jst;    const char *value=env->GetStringUTFChars(obj,JNI_FALSE);    if(startNode->getvalue()== nullptr){        startNode->set(key,value);    }else{        Node *elem=new Node(key,value);        elem->next=endNode;        elem->pre=endNode->pre;        endNode->pre->next=elem;        endNode->pre=elem;    }}JNIEXPORT jint JNICALL Java_com_xuye_xy_socket_jni_LinkList_size(JNIEnv *env,jobject thiz){    return count;}JNIEXPORT jobject JNICALL Java_com_xuye_xy_socket_jni_LinkList_next(JNIEnv *env,jobject thiz){    if(nextNode!= nullptr&&nextNode->next!= nullptr&&nextNode->next->getvalue()!= nullptr){        const char *value=nextNode->next->getvalue();        int key=nextNode->next->getkey();        jobject nodeobj=newNode(env,key,value);        nextNode->next=nextNode->next->next;//下一个        return nodeobj;    }    return nullptr;}JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_prenext(JNIEnv *env,jobject obj){    nextNode=new Node();    nextNode->next=startNode;}JNIEXPORT jboolean JNICALL Java_com_xuye_xy_socket_jni_LinkList_hasnext(JNIEnv *env,jobject thiz){    if(nextNode!= nullptr&&nextNode->next!= nullptr&&nextNode->next->getvalue()!= nullptr){        return true;    }    return false;}JNIEXPORT jstring JNICALL Java_com_xuye_xy_socket_jni_LinkList_get(JNIEnv *env,jobject thiz,jint key){    Node *temp=new Node();    temp->next=startNode;    while (temp->next!= nullptr){        if(temp->next->getkey()==key)            return env->NewStringUTF(temp->next->getvalue());        temp=temp->next;    }    return nullptr;}jobject newNode(JNIEnv *env,int key, const char *value){    jclass nodeclass=env->FindClass("com/xuye/xy/socket/java/Node");//获取到Node类    jmethodID nodeinit=env->GetMethodID(nodeclass,"<init>","()V");//获取到Node实例化方法    jmethodID   nodesetkey=env->GetMethodID(nodeclass,"setKey","(I)V");//获取到设置Key的方法    jmethodID nodesetvalue=env->GetMethodID(nodeclass,"setValue","(Ljava/lang/String;)V");//获取到设置value的方法    jobject nodeobj=env->NewObject(nodeclass,nodeinit);//创建一个新的Node    env->CallVoidMethod(nodeobj,nodesetkey,key);//设置key    jstring valuestr=env->NewStringUTF(value);    env->CallVoidMethod(nodeobj,nodesetvalue,valuestr);//设置value    return nodeobj;}

MainActivity的调用:

    private LinkList list;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // Example of a call to a native method        TextView tv = (TextView) findViewById(R.id.sample_text);        list=new LinkList();        for(int i=0;i<1000;i++){            list.add(i,new String("第"+i+"个"));        }        list.prenext();        StringBuilder builder=new StringBuilder();        while (list.hasnext()){            Node node=list.next();            node.log();        }        tv.setText(list.get(5));    }

执行后打印结果如下:
这里写图片描述
在这里对于基础学习有2个地方需要注意:
第一个是在构建对应的.h文件时,可以利用javah命令生成和Java对应的.h文件;
第二个是在需要调用Java对象或者方法的时候,可以利用javap命令获取到签名,在C中进行调用。