美文网首页Android-NDK/JNI
Android NDK开发:用C++手写一个简单的ArrayLi

Android NDK开发:用C++手写一个简单的ArrayLi

作者: itfitness | 来源:发表于2021-03-14 16:31 被阅读0次

    目录

    相关文章

    Android NDK开发:java调用dll动态链接库方法
    Android NDK开发:JNIEnv的原理
    Android NDK开发:C修改Java的属性
    Android NDK开发:C调用Java层方法
    Android NDK开发:C创建Java层的对象
    Android NDK开发:C操作Java层的数组
    Android NDK开发:Native层的变量管理及静态缓存
    Android NDK开发:Native层的异常处理
    Android NDK开发:结构体的偏移量及所占大小
    Android NDK开发:运算符重载与友元函数

    实现原理

    整个ArrayList的实现原理是参照Java中的ArrayList的原理来写的,本质上也是利用的数组实现的,也就是最开始创建一个长度为10的数组,然后不断的对数组中的各个元素赋值,当添加的元素数量超过当前数组长度的时候就重新创建一个新的数组,而新数组的长度是原来数组长度的1.5倍,然后再将原数组的数据复制到新数组中。

    代码展示

    C++代码
    整个C++的代码比较简单,主要运用的基础知识点有:面向对象、模板类、动态分配内存、类型转换

    #include <malloc.h>
    
    template <class T>
    class ArrayList
    {
    public:
        ArrayList();
        ~ArrayList();
        void add(T t);
        T get(int index);
        int size();
        T remove(int index);
    private:
        int index = 0;
        int len = 10;
        T* arr;
        void resizeArr();
    };
    
    /**
     * 创建的时候分配相应的空间
     * @tparam T
     */
    template <class T>
    ArrayList<T>::ArrayList()
    {
        this->arr = (T*)malloc(sizeof(T) * this->len);
    }
    
    /**
     * 释放的时候将相应的空间一起释放
     * @tparam T
     */
    template <class T>
    ArrayList<T>::~ArrayList()
    {
        if (this->arr != NULL) {
            free(this->arr);
        }
    }
    
    /**
     * 当长度不够的时候重新设置长度
     * @tparam T
     */
    template <class T>
    void ArrayList<T>::resizeArr()
    {
        T * newArr = (T*)malloc(sizeof(T) * this->len);
        for (int i = 0; i < this->index; i++) {
            newArr[i] = this->arr[i];
        }
        free(this->arr);
        this->arr = NULL;
        this->arr = newArr;
    }
    
    /**
     * 添加元素
     * @tparam T
     * @param t
     */
    template <class T>
    void ArrayList<T>::add(T t)
    {
        if (this->index < this->len) {
            this->arr[this->index] = t;
            this->index++;
        }
        else
        {
            this->len = this->len + (this->len >> 1); //长度变为原来长度的1.5倍(右移一位相当于除以2)
            this->resizeArr();
            this->add(t);
        }
    }
    
    /**
     * 获取元素
     * @tparam T
     * @param index
     * @return
     */
    template <class T>
    T ArrayList<T>::get(int index)
    {
        if (this->index > index) {
            return this->arr[index];
        }
        else {
            return NULL;
        }
    }
    
    /**
     * 获取集合的大小
     * @tparam T
     * @return
     */
    template <class T>
    int ArrayList<T>::size() {
        return this->index;
    }
    
    /**
     * 移除并返回被移除的元素
     * @tparam T
     * @param index
     * @return
     */
    template <class T>
    T ArrayList<T>::remove(int index) {
        if (index >= this->index) {
            return NULL;
        }
        else {
            T t = this->arr[index];
            for (int i = index; i < this->index; i++) {
                this->arr[i] = this->arr[i + 1];
            }
            this->index--;
            return t;
        }
        
    }
    

    下面的Native的实现方法,运用了OpenCv里的一个技巧,就是创建完对象后将指针以long类型返回,等再次调用Native方法的时候再将其转成指针

    #include <jni.h>
    #include <string>
    #include "ArrayList.cpp"
    #include <android/log.h>
    extern "C" JNIEXPORT jlong JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_createArrayList(
            JNIEnv* env,
            jobject jobj) {
        //这里是仿照OpenCv的Android依赖的源码实现的,将创建的ArrayList指针以long类型返回,等调用Native方法的时候再转成指针
        ArrayList<int>* arrlist = new ArrayList<int>();
        long addr = (long)arrlist;
        return addr;
    }
    
    extern "C" JNIEXPORT void JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_add(
            JNIEnv* env,
            jobject jobj,
            jlong addr,
            jint element) {
        ArrayList<int>* arrlist = (ArrayList<int>*)addr;
        arrlist->add(element);
    }
    
    extern "C" JNIEXPORT jint JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_get(
            JNIEnv* env,
            jobject jobj,
            jlong addr,
            jint index) {
        ArrayList<int>* arrlist = (ArrayList<int>*)addr;
        return arrlist->get(index);
    }
    
    extern "C" JNIEXPORT jint JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_size(
            JNIEnv* env,
            jobject jobj,
            jlong addr) {
        ArrayList<int>* arrlist = (ArrayList<int>*)addr;
        return arrlist->size();
    }
    
    extern "C" JNIEXPORT jint JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_remove(
            JNIEnv* env,
            jobject jobj,
            jlong addr,
            jint index) {
        ArrayList<int>* arrlist = (ArrayList<int>*)addr;
        return arrlist->remove(index);
    }
    
    /**
     * 释放空间
     */
    extern "C" JNIEXPORT void JNICALL
    Java_com_itfitness_myarraylist_MyArrayList_release(
            JNIEnv* env,
            jobject jobj,
            jlong addr) {
        ArrayList<int>* arrlist = (ArrayList<int>*)addr;
        delete(arrlist);
    }
    

    Kotlin代码
    Kotlin代码就比较简单了,主要是对native方法的调用

    class MyArrayList{
        private val addr:Long //存储NDK层的ArrayList的地址
        companion object {
    
            // Used to load the 'native-lib' library on application startup.
            init {
                System.loadLibrary("native-lib")
                //System.loadLibrary("ArrayList")
            }
        }
        external fun createArrayList(): Long
        external fun get(addr:Long,index:Int): Int
        external fun add(addr:Long,element:Int)
        external fun remove(addr:Long,index:Int): Int
        external fun size(addr:Long): Int
        external fun release(addr:Long)
        init {
            addr = createArrayList()
            Log.e("创建的地址","$addr")
        }
    
        /**
         * 添加元素
         */
        fun add(element: Int){
            add(addr,element)
        }
    
        /**
         * 获取元素
         */
        fun get(index: Int):Int{
            return get(addr,index)
        }
    
        /**
         * 获取大小
         */
        fun size():Int{
            return size(addr)
        }
    
        /**
         * 移除并返回元素
         */
        fun remove(index: Int):Int{
            return remove(addr,index)
        }
    
        /**
         * GC回收的时候将C++的对象释放掉
         */
        @Throws(Throwable::class)
        protected fun finalize(){
            release(addr)
        }
    }
    

    实现效果

    Activity中的调用代码如下:

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            var arrayList = MyArrayList()
            for(i in 0 until 20){
                arrayList.add(i)
            }
            Log.e("移除前的大小","${arrayList.size()}")
            //移除掉一个值
            arrayList.remove(10)
            Log.e("移除后的大小","${arrayList.size()}")
            for (i in 0 until arrayList.size()){
                val element = arrayList.get(i)
                Log.e("获取的值","$element")
            }
        }
    }
    

    实现效果如下:


    案例源码

    https://gitee.com/itfitness/MyArrayList.git

    相关文章

      网友评论

        本文标题:Android NDK开发:用C++手写一个简单的ArrayLi

        本文链接:https://www.haomeiwen.com/subject/qvgqcltx.html