Android Cursor浅析

Android中Cursor的使用 在Android开发中,我们经常需要与数据库进行交互,而Cursor提供了一种方便的方式来处理查询结果集。上述代码创建了一个名为"mydatabase.db"的数据库,并在其中创建了一个名为"mytable"的表,表中包含"id"和"name"两列。在示例中,我们选择了所有列,没有设置选择条件和排序方式。然后,我们可以通过索引获取相应的列值,并对结果进行处理,例如打印或展示在用户界面上。最后,我们记得在使用完Cursor和数据库后关闭它们,以释放资源。上述代码中,我们首先获取可读的数据库实例,然后使用。 阅读详情

1. 本文目的

Android ContentProvider提供了进程间数据交换的一种机制。而数据库的查询就是这种机制的应用。那么app通过Uri查询数据库而得到的Cursor究竟是个什么东西?为何可以为我们提供另一个进程的数据?本文以getContentResolver().query(……)函数为起点,全面分析Cursor家族关系类图,理清Cursor跨进程通信的机制。

1.1 客户端的Cursor对象

假设B进程中有一个ContentProvider,A进程通过Uri查询这个ContentProvider,从而得到一个Cursor。可能的代码如下:

ContentResolver cr = mContext.getContentResolver();//mContext是一个Context对象
Cursor cs = cr.query(uri,null,null,null,null);

为了知道上述代码得到的Cursor的真实面貌,我们需要看下上述query的调用途径。query函数的实现如下:

    public final Cursor query(final Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder,
            CancellationSignal cancellationSignal) {
        IContentProvider unstableProvider = acquireUnstableProvider(uri);
        //省略无关代码
        try {
            //省略无关代码
            Cursor qCursor;
            try {
                qCursor = unstableProvider.query(uri, projection,
                        selection, selectionArgs, sortOrder, remoteCancellationSignal);
            } catch (DeadObjectException e) {
              //省略无关代码
            }
            if (qCursor == null) {
                return null;
            }
           //省略无关代码
            CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
                    stableProvider != null ? stableProvider : acquireProvider(uri));
            stableProvider = null;
            return wrapper;
        } catch (RemoteException e) {
           //省略无关代码
        } finally {
          //省略无关代码
        }
}

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 为了方便分析,省略了无关代码。从以上代码可以看出: 

1.通过query函数返回的Cursor是一个CursorWrapperInner对象;

2.CursorWrapperInner是一个包装类,是通过以IContentProvider 的query函数返回的Cursor对象构建的;

那么有两个疑问:

1.IContentProvider 的query函数返回的Cursor,真实对象是?

2.CursorWrapperInner类起什么作用,为什么要把IContentProvider 的query函数返回的Cursor作为参数,从新构造一个CursorWrapperInner?

首先来看下类图:

从上述类图可以得知:

CursorWrapperInner是ContentResolver的内部类,继承自CrossProcessCursorWrapper。CrossProcessCursorWrapper从名字上看是一个实现了跨进程通信的Cursor包装类。从类图上也验证了这一点,CrossProcessCursorWrapper继承自CursorWrapper,实现了CrossProcessCursor接口。而CursorWrapper是一个包装类,它实现了Cursor接口的所有功能,它内部含有一个mCursor成员变量指向一个Cursor接口,从而可以得知,这是一个代理模式。CursorWrapper委托它内部的mCursor对象来实现所有的Cursor功能接口。CrossProcessCursor继承自Cursor,它主要是用于跨进程通信。

综上,目前我们可以知道,CrossProcesCursorWrapper实现了所有的Cursor接口,但是这些接口功能的完成全部委托它父类内部的mCursor来完成。那么mCursor的真实对象是什么呢?暂且推测,mCursor应该是一个实现了CrossProcessCursor的对象。

总结:客户端拿到的Cursor的真实对象是:CursorWarpprtInner类。

1.2 CursorWrapper内部的Cursor真实面目

从上节我们已经知道,通过代理模式,CursorWrapperInner最终会委托CursorWrapper来完成实际功能。现在就看看CursorWrapper内部的mCursor的真实面目。mCursor来自于IContentProvider 的query函数所返回的Cursor对象。那么这个Cursor对象是啥呢?那就要看看IContentProvider的query函数的实现了。IContentProvider的实际上是一个ContentProviderProxy对象。它是一个代理类,也是一个Binder的Bp端,将函数调用的参数打包发送给ContentProviderNative,最终由ContentProviderNative把来调用ContentProvider的具体函数。

ContentProviderProxy,ContentProviderNative,ContentProvider,IContentProvider的关系如下:

下面是ContentProviderProxy的query实现:

    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
                    throws RemoteException {
        BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        try {
            data.writeInterfaceToken(IContentProvider.descriptor);

            url.writeToParcel(data, 0);
            int length = 0;
            if (projection != null) {
                length = projection.length;
            }
            data.writeInt(length);
            for (int i = 0; i < length; i++) {
                data.writeString(projection[i]);
            }
            data.writeString(selection);
            if (selectionArgs != null) {
                length = selectionArgs.length;
            } else {
                length = 0;
            }
            data.writeInt(length);
            for (int i = 0; i < length; i++) {
                data.writeString(selectionArgs[i]);
            }
            data.writeString(sortOrder);
            data.writeStrongBinder(adaptor.getObserver().asBinder());
            data.writeStrongBinder(cancellationSignal != null ? cancellationSignal.asBinder() : null);

            mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);

            DatabaseUtils.readExceptionFromParcel(reply);

            if (reply.readInt() != 0) {
                BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
                adaptor.initialize(d);
            } else {
                adaptor.close();
                adaptor = null;
            }
           return adaptor;
        } catch (RemoteException ex) {
            adaptor.close();
            throw ex;
        } catch (RuntimeException ex) {
            adaptor.close();
            throw ex;
        } finally {
            data.recycle();
            reply.recycle();
        }
    }
从上面代码可以得之,query函数返回的Cursor的真实对象是BulkCursorToCursorAdaptor。在query函数内部通过 transact函数把query请求传递到ContentProviderNative端。 transact执行完毕后会返回一个Parcel reply。从reply中构造一个 BulkCursorDescriptor。然后由这个 BulkCursorDescriptor初始化BulkCursorToCursorAdaptor。BulkCursorToCursorAdaptor中一个相当重要的赋值操作如下:

    public void initialize(BulkCursorDescriptor d) {
        mBulkCursor = d.cursor;
        mColumns = d.columnNames;
        mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
        mWantsAllOnMoveCalls = d.wantsAllOnMoveCalls;
        mCount = d.count;
        if (d.window != null) {
            setWindow(d.window);
        }
    }

d.window是一个CursorWindow对象。这个对象实际上代表着一块共享内存,存储着查询后的结果集。详情请参见: http://blog.youkuaiyun.com/ifloveelse/article/details/28394103。而mBulkCursor是一个IBulkCursor接口。这个接口起到数据传输的作用。分析到这一步,Cursor的”全家幅“更加的详细了:


总结:在本小节开头就提出的问题:CursorWrapper内部的Cursor真实面目是谁?现在也可以解答了:BulkCursorToCursorAdaptor。从名字上看这是个适配器,将Cursor的功能接口通过转换,调用IBulkCursor来实现。自此,上面的这个类图就是APP端进程中Cursor的全部关系了。那么IBulkCursor又是做什么的呢?下一小节讲解。

1.3 IBulkCursor家族

BulkCursorToCursorAdaptor的mBulkCursor来自于ContentProviderNative的返回值。为了弄清楚IBulkCursor的真实面貌,还要去看看ContentProviderNative的实现。

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        try {
            switch (code) {
                case QUERY_TRANSACTION:
                {
                    data.enforceInterface(IContentProvider.descriptor);

                    Uri url = Uri.CREATOR.createFromParcel(data);

                    // String[] projection
                    int num = data.readInt();
                    String[] projection = null;
                    if (num > 0) {
                        projection = new String[num];
                        for (int i = 0; i < num; i++) {
                            projection[i] = data.readString();
                        }
                    }

                    // String selection, String[] selectionArgs...
                    String selection = data.readString();
                    num = data.readInt();
                    String[] selectionArgs = null;
                    if (num > 0) {
                        selectionArgs = new String[num];
                        for (int i = 0; i < num; i++) {
                            selectionArgs[i] = data.readString();
                        }
                    }

                    String sortOrder = data.readString();
                    IContentObserver observer = IContentObserver.Stub.asInterface(
                            data.readStrongBinder());
                    ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
                            data.readStrongBinder());

                    Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder,
                            cancellationSignal);
                    if (cursor != null) {
                        CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor(
                                cursor, observer, getProviderName());
                        BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();

                        reply.writeNoException();
                        reply.writeInt(1);
                        d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeNoException();
                        reply.writeInt(0);
                    }

                    return true;
                }
            }
…………

上面的代码是ContentProviderNative中onTransact函数对query的处理。在这部分代码中,又冒出了个 CursorToBulkCursorAdaptor对象。这个对象的构造函数是一个Cursor对象。那么这个Cursor对象的又是谁呢?逻辑越来越复杂了。Cursor是由query函数返回。由1.2节中所提供的ContentProvider的类图可以得之,这个query调用的是ContentProvider的query函数。那么ContentProvider的query函数中的Cursor又是哪里来的呢?这里直接给出答案:SQLiteDatabase。ContentProvider是一个抽象类,我们需要自己实现其中的query函数。一般,在query中,我们通过SQLiteDatabase查询自定义的数据库,得到一个Cursor对象。这个过程就省略。我们需要知道的是:SQLiteDatabase的query函数返回一个Cursor。这个Cursor用来构建了一个 CursorToBulkCursorAdaptor对象。

下面就看看SQLiteDatabase返回的Cursor的真实面貌。下面是SQLiteDatabase中query的最终调用函数。具体的代码可以参考SQLiteDatabase.java文件:

    public Cursor rawQueryWithFactory(
            CursorFactory cursorFactory, String sql, String[] selectionArgs,
            String editTable, CancellationSignal cancellationSignal) {
        acquireReference();
        try {
            SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
                    cancellationSignal);
            return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
                    selectionArgs);
        } finally {
            releaseReference();
        }
    }
由上面的代码可以得之,Cursor来自于SQLiteDirectCursorDriver的query。那不妨在看看其query的实现:

    public Cursor query(CursorFactory factory, String[] selectionArgs) {
        final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
        final Cursor cursor;
        try {
            query.bindAllArgsAsStrings(selectionArgs);

            if (factory == null) {
                cursor = new SQLiteCursor(this, mEditTable, query);
            } else {
                cursor = factory.newCursor(mDatabase, this, mEditTable, query);
            }
        } catch (RuntimeException ex) {
            query.close();
            throw ex;
        }

        mQuery = query;
        return cursor;
    }

这里我们假设factory为空,那么此处的Cursor终于露出了它的真实面貌: SQLiteCursor。 一路跟踪的真是辛苦,水落石出了!

通过下面的类图我们整理下我们的思路:


从图中可以看出BulkCursorToCursorAdaptor的成员变量的mBulkCursor是一个IBuilCursor接口,它的真实对象其实是一个BulkCursorProxy。BulkCursorProxy是一个代理端,也是一个Bp端,通过Binder通信把函数调用请求转发给另一个进程中的Bn端BulkCursorNative。图中,绿线方框部分运行在app进程中,红线方框部分运行在ContentProvider进程中。

CursorToBulkCursorAdaptor中的mCursor的真实对象也揭晓了:SQLiteCursor。从名字上看也知道这个对象和SQLite有关系了。它内部有一个SQLiteQuery,负责数据库的查询和CursorWindow的建立。红线和绿线方框的交叉处CursorWindow是共享内存的抽象。在两个进程中都存在一份映射。

自此,Cursor的分析全部结束。


Cursor 在实际项目中的使用经验分享 今天站在⼀个相对写程序经验多⼀点的开发者的⻆度,跟⼤家去分享 cursor 这个软件。从实际⼯作场景的⻆度和⼤家聊聊,我们如何去使⽤ cursor 不断维护代码,不断迭代更新的。这个软件我在深度使⽤了两个多星期后,就买了它的 Pro 版了,现在每个⽉ 500 次的 Pro fast 使⽤的额度已经让我使⽤完了,我的使⽤深度已经算是很深的了。我最早的时候是在⽤ChatGPT 这类 AI ⼯具,后来买了 GitHub Copilot 进⾏辅助编码。 阅读详情

相关推荐

UniDexGrasp++算法实战:无需预生成姿态的灵巧抓取测试指南

本文详细解析了UniDexGrasp++算法在灵巧抓取测试中的实战应用,该算法无需预生成姿态即可实现高效抓取,特别适合处理形状不规则的物体。文章涵盖了环境配置、数据集优化、训练流程及实际测试中的调参技巧,帮助开发者快速掌握这一ICCV 2023提出的先进算法。

weixin_29045585的博客 279

Android中的Cursor

Cursor 1. 什么是Cursor Cursor就是游标,可以理解为我们在输入文本框闪烁的光标,标记我们要输入的位置。那什么是光标呢 这个一闪一闪的竖线就是光标。而我们的Cursor也是用来标记位置,标记我们要读取数据的位置。 2. Cursor对象获取 我们这里用内容提供者进行举例。 //指定获取字段 String[] columns = new String[]{MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColu

weixin_47323733的博客 6039

高通Sensor Tuning实战:手把手教你用Chromatix生成并打包bin文件(附避坑指南)

本文详细介绍了高通Sensor Tuning的全流程实战,从Chromatix配置到Bin文件加载验证。通过手把手教程,帮助开发者掌握Chromatix工具链的使用,避免常见配置错误,提升调试效率。特别针对kalama等新一代平台,提供经过验证的解决方案和避坑指南。

ios99的博客 483

cursor android,Android Cursor用法

Cursor作用类似于java中resultSet,把查询到的结果集封装在一个Cursor对象当中。cursor就像是结果集上的一个游标,可以向前向后移动。常用方法:moveToFirst(); moveToFirst(); 移动到第一行或最后一行moveToNext();MoveToPrevious() 向前移动一行或向后移动一行moveToPosition(positon) 移动到指定位置注:...

weixin_42549496的博客 5986

优化问题-半正定规划(Semi-Definite Program, SDP)

半正定规划(Semi-Definite Program, SDP)在MIMO无线通信相关的信号处理中具有广泛的应用,在某些场景可以分析证明SDP的得到的解释原问题的全局最优化或者次优解。

qq_33668008的博客 1万+

保姆级教程:在PyCharm里用Continue插件一键接入DeepSeek API(含乱码修复)

本文详细介绍了如何在PyCharm中通过Continue插件无缝集成DeepSeek API,提供从环境准备到高级配置的全流程指南,包括解决常见的乱码问题。通过本教程,开发者可以轻松实现AI编程助手的高效调用,提升代码编写和调试效率。

weixin_30275415的博客 850

Android Studio Cursor里面的数据获取并且使用

在使用Android Studio,使用数据库时查询用到cursor。但是怎么查询到之后,怎么使用里面的数据呢?在这里以我用的Sqlite为例:使用Cursor对象获取查询结果rawQuery()方法返回的查询结果为Cursor类的对象。Cursor可称为”数据指针“,要读取查询结果中某一个记录,就必须将Cursor指标指到它,之后才能读取其内容。那么怎么页面之间传输获取到的数据呢?

qq_52078947的博客 4456

iOS自动化之打包-xcodebuild命令行打包.app并安装到ios模拟器

xcode xcodebuild xcrun ios模拟器 iOS UI自动化测试 ios自动打包安装到ios模拟器

z12347891的博客 5078

【Android】开局一行码,数据自己填(浅析安卓数据存储)

对于Android开发者而言,掌握数据存储技术是构建强大应用的必备技能。Android提供了多种数据存储方案来满足不同的需求。本篇博客,我们将探讨Android中两种核心的数据存储技术:SharedPreferences和SQLite数据库。在Android开发中,对于轻量级数据的存储,SharedPreferences无疑是一个简单而强大的工具。它允许开发者以键值对的形式存储和检索数据,非常适合用于存储应用配置、用户偏好设置等。

2301_79344902的博客 1178

信息奥赛课课通(C++)p154-1近似排序

试题描述 读入一对正整数,将这两个数之间(包括这两个数本身)的所有数按下述特别规则排序后输出,该特别规则是按两数倒过来的值进行比较决定其大小,如30倒过来为3,29倒过来为92,则29大于30. 输入要求 1行,包含两个用空格隔开的自然数,这两个自然数给出了待排序数的范围,其中1≤第一个数≤第二个数≤999999999,两个数之差不超过100. 输出要求 输出排序后的数据,每行输出...

mengdicfm的博客 7283

9篇9章1节:认识 SHARE 数据库

SHARE数据库是欧洲最大的跨国老龄化追踪调查项目,覆盖28个欧洲国家和以色列的50岁及以上人群。自2004年启动以来,已完成14-16万受访者的50-60万次访谈,形成跨度20年的纵向数据。该数据库采用标准化的多阶段抽样方法,收集健康、经济和社会关系等领域的多维度信息,具有高度的跨国可比性。SHARE与美国HRS、英国ELSA等调查对接,构成全球老龄化研究网络。数据免费向科研人员开放,但需注册并承诺仅用于非商业性研究。该项目由欧盟委员会等多方资助,为老龄化研究和政策制定提供了重要实证依据。

MD Code 902

Android 内存浅析【泄漏、溢出】【二】

内存溢出之Bitmap      可以说出现OutOfMemory问题的绝大多数人,都是因为Bitmap的问题。因为Bitmap占用的内存实在是太多了,它是一个“超级大胖子”,特别是分辨率大的图片,如果要显示多张那问题就更显著了。     如何解决Bitmap带给我们的内存问题?     第一、及时销毁。     虽然,系统能够确认Bitmap分配的内存最终会被销毁,但是由于它占用的内存过

老牛比 4413

基于电阻分压 + 电压跟随器的直流母线电压采样电路

摘要:本文介绍了一种基于电阻分压和电压跟随器的直流母线电压采样电路设计。该电路通过R38(240kΩ)和R41(20kΩ)组成的分压网络将高电压(如48V)降至3V,再经GS8331运放构成的电压跟随器进行隔离缓冲,最后通过RC滤波输出给ADC采集。重点分析了关键元件的选型要求:分压电阻需高精度、低温度系数;运放需高输入阻抗、低失调电压;滤波电容需稳定性好。该设计适用于工业电源、新能源BMS、变频器等需要高精度电压采样的应用场景。

qq_37999850的博客 891

Android 在使用Cursor时踩的坑。

至于前面的 @SuppressLint("Range") 是因为获取ColumnIndex索引值的时候,正常情况下是0 1 2 3 这样按顺序排下去的,如果找不到就会返回 -1 ,而使用getString()给的是大于等于0的值,所以直接用会有冲突,需要 @SuppressLint("Range") 这句话去限制下范围。所以在这种情况下,接下去使用getString()方法便会出错溢出。今儿写获取数据库数据时候遇到了使用cursor.getString()的方法,结果运行的时候app直接崩溃。

qq_50401364的博客 860

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

对Android中的Cursor一些浅显见解

之前一直搞不懂Cursor的数据模型是怎么样的,等到看到下面别人博客中把Cursor比作.net中的DataReader才明白,原来是这么回事。但是没 学过.Net的同志可能还是不明白Cursor是怎么一回事,怎么取它的数据,和它的数据为什么那么取。 上面的表代表的是一个cursor对象。 当我们用query方法查询到的是一个指向cursor对象第一行的前面一行数据,即上图中的...

kite5121314的专栏 1万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【转载】Android中的Cursor到底是什么?如何理解Cursor的方法都在做什么事情?

安卓SQLite使用的时候遇到光标Cursor,这Cursor到底是什么?

7zwang的博客 1428

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

零基础挑战用cursor开发一个安卓app——打包成apk并上传到GitHub

随即,cursor就将app基本功能完成了,然后经过几轮简单的调试及排除错误,app就完成了,再经过几轮对话,app就已经完全可用了,直到写完readme,总共只用了23轮对话,可以说非常之迅速。今天要尝试开发的是防止手机数据被恢复的app,打开Android Studio,创建项目,打开cursor选中刚才创建项目的文件夹,Ctrl+i调出Composer,直接提出需对app的需求。这里,由于版本的不同,我在选择release时,没有v1、v2这两个选项,不过不影响app打包。具体过程参考了大佬@

weixin_45163575的博客 7257

AI智能编程工具Cursor使用介绍

这是一款为使用人工智能编程而构建的编辑器,集成GPT-4,拥有强大的AI代码生成能力,它可以根据你的需求,自动生成代码,分析代码,优化代码,并可以基于某个代码片段和你展开讨论。本文详细介绍了Ai编辑器Cursor的使用方式,帮助大家快速了解并上手。需要注意的是,目前cursor仍然是免费测试版本,目前还在快速迭代中,如果生成的代码不符合你的要求,你可以换一种表述重新生成结果,这一点和ChatGPT使用不同的提示词生成不同的结果是一样的。

qq_36756227的博客 1万+

我用 Cursor 一天读懂了上万行代码!从零基础到精通,收藏这篇就够了!

在 AI 时代,阅读代码不必再那么痛苦。善用 Cursor 这样的智能工具,能让我们事半功倍。正如"工欲善其事,必先利其器",拥抱新技术不仅能帮助我们更快地理解代码,更能提升整体的开发效率。本文限于篇幅,只介绍了 Cursor 的一些基础用法。事实上,随着 AI 技术的快速发展,每天都有新的工具和方法被开发出来。如果你也对 AI 编程感兴趣,欢迎加入我的付费社群深度交流(微信公众号同名)。让我们一起在 AI 浪潮中不断进步,用智能工具让编程更轻松!

yy1715713348的博客 1275

纠正编码错误篇 (3)Cursor、Exception 常见警告及解决办法

前言这一篇接着讲讲一些比较有意思的黄色警告(Warning),仔细的想了一下,也就想起来了cursor,Exception是最近才遇到的,所以也顺便说一下。对于系统的一般的警告提示,比如,局部变量不要赋值啊 ,if条件恒等啊,方法已经过时之类的,这里就不说了。正文CursorCursor是光标的意思,主要就是应用在数据库中,我们去查询一条或多条记录,会返回查询结果的光标,通过对这个光标进行循环,得到

珠穆朗玛小王子的博客 1万+

零基础挑战用cursor开发一个安卓app——一键批量卸载指定APP

首先,请出我们的主角cursor,选定文件夹,ctrl+i呼唤出我亲爱伙伴composer,告诉他我需要一个“一件卸载应用”app,很快cursor就帮我完成了文件的创建和代码的编写,然而,项目并不能运行。直到此时,功能已经完备,我还用豆包给它生成了个图标,做了开屏美化,甚至我都准备在酷安上架了,到这时候也只用了大概1个小时。感觉这个名字不太对,就出现了图7,忘了什么原因出现了图8,然后还缺少个“顶已选中应用”功能,就出现了图9,本来还想这个“选中置顶”按钮有点多余,转念一想也没有更好的方案,就保留了。

weixin_45163575的博客 3481

Android Cursor自动更新的实现和原理

Android Cursor自动更新的实现和原理 在Android日常开发中,时常会请求数据到Cursor,然后再通过Cursor获取数据。像SQLiteDatabase和ContentProvider都使用了Cursor。在这些应用中,往往希望当数据发生改变时,Cursor也会自动的更新数据。这篇文章,我就会向你阐述如何通过Android自身的API实现Cursor的自动更新。另外我还将向你阐...

到达的专栏 4653

Android Cursor AI实践技巧

摘要:本文介绍了在Android开发中合理配置Cursor(AI代码编辑器)规则的方法,以提升AI生成代码的质量。核心思路是通过结构化提示词、自定义指令和上下文管理约束AI输出,包括技术栈约束、代码风格规范、项目结构固定和上下文关联。具体配置方法包括创建项目规则模板、自定义常用指令、管理上下文引用已有代码、明确技术栈版本限制以及通过示例代码统一风格。这些实践能帮助开发者减少代码修改量,提高开发效率。

要乐观,要积极,多笑,多照镜子 3592

Android Cursor AI代码编辑器

Cursor是一款AI辅助编程编辑器,深度集成自然语言交互功能,显著提升Android开发效率。支持快速生成Kotlin/Java代码、XML布局,并能解释复杂逻辑。通过简单指令即可创建项目结构、生成登录页面布局、实现按钮点击事件等核心功能,还能自动生成Retrofit网络请求代码。编辑器支持代码解释和注释生成,简化开发流程,使开发者更专注于业务逻辑而非基础编码工作。

要乐观,要积极,多笑,多照镜子 3019
上一篇: JNI设计概述
下一篇: OpenMax的数据类型
Sailingthink
博客等级 码龄14年 31粉丝 26原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值