Android 第十二课 使用LitePal操作数据库(记得阅读最后面的注意事项哦)

一、LitePal简介

1、(新建项目LitePalTest)

正式接触第一个开源库---LitePal
LitePal是一款开源的Android 数据库框架,它采用了对象关系映射(ORM)的模式。

2、配置LitePal,编辑app/build.gradle文件,在dependencies闭包中添加如下内容:
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'


    compile 'org.litepal.android:core:1.4.1'
}

这样我们就成功把LitePal成功引入当前项目中了,接下来需要配置litepal.xml文件。右击app/src/main目录,new一个
Directory,命名为assets,然后在assets目录下,新建一个litepal.xml。编辑,添加代码,如下:
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
    <dbname value = "BookStore222">
    </dbname>


    <version value = "1">
    </version>


    <list>
     </list>


</litepal>


其中,<daname>标签用于指定数据库名,<version>标签用于指定数据库版本号,<list>标签用于指定所有的映射模型。


3、最后需要配置一下LitePalApplication,修改AndroidManifest.xml中的代码,如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.litepaltest">


    <application

        android:name="org.litepal.LitePalApplication"


        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>


</manifest>
我们项目的application配置为org.litepal.LitePalApplication,只有这样才能让LitePal的所有功能都可以正常
工作,关于application的作用,我们再行介绍。


二、创建和升级数据库


LitPal采取的是对象关系映射(ORM)的模式,简单说就是我们使用的编程语言是面向对象语言,而使用的数据库是
关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射。


使用LitePal,可以用面向对象的思维来实现功能,定义一个Book类,代码如下:
package com.example.litepaltest;


/**
 * Created by ZHJ on 2018/3/4.
 */


public class Book {
    private int id;
    
    private String author;
     
    private  double price;
    
    private  int pages;
    
    private String name;


    public int getId() {
        return id;
    }


    public String getAuthor() {
        return author;
    }


    public double getPrice() {
        return price;
    }


    public int getPages() {
        return pages;
    }


    public String getName() {
        return name;
    }


    public void setId(int id) {
        this.id = id;
    }


    public void setAuthor(String author) {
        this.author = author;
    }


    public void setPrice(double price) {
        this.price = price;
    }


    public void setPages(int pages) {
        this.pages = pages;
    }


    public void setName(String name) {
        this.name = name;
    }
}


这是一个典型的Java bean,在Book中我们定义了id,author,price,pages,name 这几个字段,并生成相应的getter和setter
方法(先将类中的字段定义好,按下Alt+Insert,在弹出的对话框中选择Getter和Setter,接着使用Shift将所有字段选中。就会自动生成相应的getter和setter方法。)
相信你已经猜到了,Book类就会对应数据库中的Book表,而类中的每个字段分别对应了,表中的每个列。
接下来将Book类添加到映射模型列表中,修改litepal.xml中的代码,如下:
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
    <dbname value = "BookStore222">
    </dbname>


    <version value = "1">
    </version>


    <list>
        <mapping class = "com.example.litepaltest.Book"></mapping>
    </list>


</litepal>


这里通过<mapping>标签来声明我们要配置的映射模型类,注意是使用完整的类名。不管多少模型类需要映射,
都使用同样的方式配置在<list>标签下。


所有工作已经完成了,进行任意的一次数据库操作,BookStore222.db数据库就会被自动创建出来。
修改MainActivity中的代码,如下:
package com.example.litepaltest;


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


import org.litepal.LitePal;


public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                LitePal.getDatabase();
            }
        });
    }
}
调用 LitePal.getDatabase()方法就是一次简单的数据库操作,只要点击一下按钮,数据就自动创建完成了。运行一下程序,

然后点击Create database按钮,接着通过adb shell (主要在启动相应模拟器的情况下,在命令行输入adb shell)查看一下数据库创建情况。

注意:

activity_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="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/create_database"android:layout_width="match_parent"android:layout_height="wrap_content"android:text = "Create database"/><Buttonandroid:id="@+id/add_data"android:layout_width="match_parent"android:layout_height="wrap_content"android:text = "Add data"/><Buttonandroid:id="@+id/update_data"android:layout_width="match_parent"android:layout_height="wrap_content"android:text = "Updata data"/><Buttonandroid:id="@+id/delete_data"android:layout_width="match_parent"android:layout_height="wrap_content"android:text = "Delete data"/><Buttonandroid:id="@+id/query_data"android:layout_width="match_parent"android:layout_height="wrap_content"android:text = "Query data"/></LinearLayout>

运行程序后:



通过adb shell 查看一下数据库创建情况,(使用android 6 模拟器,android 7 似乎不可以进入超级管理员状态,也就不可以操作数据库)

adb shell 进入;

cd  data/data/com.example.项目名(listpaltest)

cd  databases

ls

如下:(具体参考《第一行代码》第二版P234)


可以看到,这里有3张表,其中android_metadata表仍然不用管,table_schema是LitePal内部使用的,我么也可以直接忽视,

book表是我们根据定义的Book类以及勒种的字段来自动生成的。

使用LitePal来升级数据库非常容易,只需要将你想改的地方,直接将版本号加1就行了。

我们要向Book表中添加一个Press(出版社)列,直接修改Book类中的代码,添加一个press字段即可。如下:

package com.example.litepaltest;/*** Created by ZHJ on 2018/3/4.*/public class Book {.....private String press;
.....public String getPress() {return press;}
....public void setPress(String press) {this.press = press;}
....}

如此同时,我们还想添加一张Category表,那么只需要新建一个Category类就可以了,代码如下:

package com.example.litepaltest;/*** Created by ZHJ on 2018/3/4.*/public class Category {private int id;private String categoryName;private int categoryCode;public void setId(int id) {this.id = id;}public void setCategoryName(String categoryName) {this.categoryName = categoryName;}public void setCategoryCode(int categoryCode) {this.categoryCode = categoryCode;}
}

改完了我们想改的东西,只需要记得将版本号加1就行了。

这里还需要添加一个新的模型类,因此也需要将它添加到映射模型列表中,修改litepal.xm中的代码,如下:

<?xml version="1.0" encoding="utf-8" ?>
<litepal><dbname value = "BookStore222"></dbname><version value = "2">//原来是1修改之后变为2</version><list><mapping class = "com.example.litepaltest.Book" <mapping clss = "com.example.litepaltest.Category"></mapping>//来声明沃我们要配置的模型类,一定要使用完整的类名。不管有多少模型类需要映射,都要以同样的方式配置在<lise>标签下。</list></litepal>

现在重新运行一下程序,点击Create database按钮,查看一下最新的建表语句,

C:\Users\ZHJ>adb shell

root@generic_x86:/ # cd data/data/com.example.litepaltest
root@generic_x86:/data/data/com.example.litepaltest # cd databases

127|root@generic_x86:/data/data/com.example.litepaltest/databases # ls
BookStore222.db
BookStore222.db-journal
qlite3 BookStore222.db                                                        <

sqlite> .table

如下:


我们可以看到,book表中新增了一个press列,category表也创建成功了。当然,LitePal还自动帮我们做了一项非常重要的工作,就是保留之前表中的所有数据,这样就不用担心数据丢失的问题了。

三、使用LitePal添加数据

使用LitePal来添加数据。

1、创建出模型类的实例。

2、再将所有要存储的数据设置好。

3、最后调用一下save()方法,就可以了。

开始动手实现,观察现有的模型类,你会发现没有继承结构的。因为LiePal进行表管理操作时不需要模型类有任何的继承结构,

但是进行CRUD操作时,就不行了。必须要继承自DataSupport类才行。因此我们需要把继承结构加上。修改Book类,代码如下:

package com.example.litepaltest;import org.litepal.crud.DataSupport;/*** Created by ZHJ on 2018/3/4.*/public class Book extends DataSupport{private int id;private String author;private  double price;private  int pages;
......
}

接着我们向Book表中添加数据,修改MainActivity中的代码,如下:

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}}); Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});}
}

我们首先创建出一个Book的实例,然后调用Book类中的各种set方法对数据进行设置,最后再调用book.save()方法就能完成数据添加操作。这个save()方法是从DataSupport类中继承来的,除了save()方法外,DataSupport类还给我们提供了丰富的CRUD方法。

现在运行程序,点击Add data按钮,此时数据应该已经添加成功了。我们打开数据库看一下。


我们点了4次Add Data 按钮,添加了4个。

四、使用LitePal更新数据库

更新数据库比添加数据稍微复杂一些,因为它的API接口比较多。

最简单的一种更新方式,就是对已经存储的对象重新设值,然后重新调用save()方法即可。

什么是已经存储的对象?

对于LitePal来说,对象是否已经存储就是根据调用model.isSaved()方法的结果来判断的,返回true表示已经存储,返回false就表示未存储,那么什么情况下,会返回true,什么情况下,会返回false?实际上,只有两种情况下model会被认为是已经存储的对象。

        一种情况是已经调用过model.save()方法去添加数据了。此时model会被认为是已存储的对象。

        另一种情况是model对象是通过LitePal提供的查询API查出来的,由于是从数据库中查到的对象,因此也会被认为是已已经存储的对象。

我们先通过第一种情况来进行验证。

首先修改MainActivity中的代码,如下:

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}});Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});   Button updataData = (Button)findViewById(R.id.update_data);updataData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Lost Symbol");book.setAuthor("Dan Brown");book.setPages(510);book.setPrice(19.95);book.setPress("Unkown");book.save();book.setPrice(10.99);book.save();}});}
}

在更新数据按钮的点击事件里面,我先是们通过上一小节学习的知识添加了一条Book数据,然后调用setPrice()方法将这本的价格进行了修改,之后再次使用了save()方法。此时LitePal会发现当前的Book对象是存储的,因此不会再向数据库中添加一条新数据,而是直接会更新当前数据。

运行程序,点击Update data 按钮。输入 select * from Book;


我们点了两次Update data 按钮,所有会更新两个数据。

但是这种更新方式只能对已存储的对象进行操作,限制比较大,我们学习另一种更新方式,修改MainActivity中的代码,如下所示:

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}});Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});Button updataData = (Button)findViewById(R.id.update_data);updataData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setPrice(14.95);book.setPress("Anchor");book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");}});}
}

在这里,我们首先new出了一个Book的实例,然后直接调用setPrice()和setPress()方法来设置要更新的数据,最后再调用updataAll()方法去执行更新操作。注意:updataAll()方法中可以指定一个条件约束,和SQLiteDatabase中的update()方法的where参数部分有点类似,但更加简洁,如果不指定条件语句,就表示更新所有数据。这里我们指定将所有书名是The Lost Symbol 并且作者是Dan Brown 书价格更新为14.95,出版社更新为Anchor。

点击Update data按钮,再次查询表中的数据情况:


可见第二本书的几个被更新成了14.95,出版社被更新成了Anchor。

在使用updateAll()方法时,还有一个非常重要的知识点,就是当你想把一个字段的值更新为默认值时,是不可以使用上面的方式来set数据的。JAVA中任何一种数据类型都会有默认值。对于所有想要将数据更新为默认值的操作,LitePal统一提供了一个setToDefault()方法,然后传入相应的列名就可以了,比如:

Book book = new Book();

book.setToDefault("pages");

book.updateAll("name =? and author","The Lost Symbol","Dan Brown");

这段代码意思是将书名是The Lost Symbol,并且做作者是Dan Brown的页数设置为默认值(就是0)。

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}});Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});Button updataData = (Button)findViewById(R.id.update_data);updataData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) { Book book = new Book();book.setToDefault("pages");book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");}});}
}

下面来检验一下:


如上观看;

因为updateAll()方法中制定了约束条件,若没有约束条件,此次更新操作会对所有的数据生效。

五、使用LitePal删除数据

使用LitePal删除数据的方式主要有两种,第一种比较简单,就是直接调用已存储对象的delete()方法就可以。所谓已存储的对象的含义我们再说一遍,就是调用过save()方法的对象,或者是通过LitePal提供的查询API查询出来的对象,都是可以直接使用delete()方法来删除对数据的。这种方式我们就不演示了。

我们来看另一种删除数据的方式。

修改MainActivity中的代码,如下:

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;
import org.litepal.crud.DataSupport;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}});Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});Button updataData = (Button)findViewById(R.id.update_data);updataData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setToDefault("pages");book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");}});Button deleteButton = (Button)findViewById(R.id.delete_data);deleteButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {DataSupport.deleteAll(Book.class,"price<?","15");}});}
}

这里调用了DataSupport.deleteAll()方法来删除数据,其中deleteAll()方法的第一个参数用来指定删除哪一张表中的数据,Book.class意味着删除Book表中的数据。后面的语句用于指定约束条件。这行代码的意思就是删除price小于15的书。

运行程序,点击按钮,查询表中数据,如下:


可以看到低于15的书的数据已经被删除了。

另外,deleteAll()方法,如果不指定约束条件,就意味着要删除表中所有的数据和updateAll()方法相似。

六、使用LitePal查询数据

使用LitePal来查询数据一点都不复杂,LitePal在查询API方面的设计及其人性化,基本上可以满足绝大多数场景的查询需求,并且代码十分整洁。比如我们打算查询表中的所有数据,使用LitePal如何完成同样的功能呢?

只需这样写:

List<Book> books = DataSupport.findAll(Book.class);

只需要调用一下findAll()方法的返回值是一个Book类型的List集合,LitePal已经自动帮我们完成了赋值操作。

修改MainActivity中的代码,如下:

package com.example.litepaltest;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;import org.litepal.LitePal;
import org.litepal.crud.DataSupport;import java.util.List;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button createDatabase = (Button) findViewById(R.id.create_database);createDatabase.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {LitePal.getDatabase();}});Button addData = (Button) findViewById(R.id.add_data);addData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setName("The Da Vinci Code");book.setAuthor("Dan Brown");book.setPages(454);book.setPrice(16.96);book.setPress("Unknown");book.save();}});Button updataData = (Button)findViewById(R.id.update_data);updataData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Book book = new Book();book.setToDefault("pages");book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");}});Button deleteButton = (Button)findViewById(R.id.delete_data);deleteButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {DataSupport.deleteAll(Book.class,"price<?","15");}});Button queryButton = (Button)findViewById(R.id.query_data);queryButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {List<Book> books = DataSupport.findAll(Book.class);for(Book book: books){Log.d("MainActivity","book name is "+"book.getName");Log.d("MainActivity","book author is "+"book.getAuthor");Log.d("MainActivity","book pages is "+"book.getPages");Log.d("MainActivity","book price is "+"book.getPrice");Log.d("MainActivity","book press is "+"book.getPress");}}});}
}

遍历List集合中的Book对象,并将其中的信息全部打印出来。现在运行一下程序,点击Query data按钮。查看logcat的打印内容。


这样,我们就已经将这条数据查询出了。

注意事项:

以上,我们是基于大牛郭霖的《第一行代码》系列书籍中的数据库内容,进行的解释。再一次从内心中迸发出的自由而不尴尬的崇高敬意。

此外,我们还可以通过操作把输入框中输入的数据,通过按钮传入到SQLite数据库,以后,我们会进行详细解释。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决关于登录校园网显示不在IP段的问题方案(要看注意事项哦!)

有时&#xff0c;登录校园网&#xff0c;账号和密码都显示正确&#xff0c;但是却显示出“账号只能在指定IP段登录”的问题。 那我们就提供了一个解决方案&#xff1a; 使用WinR,并在输入框&#xff0c;输入cmd命令&#xff1a;&#xff08;如下&#xff09;接着输入&#xff1…

页面返回顶部(方法比较)

下面就说下简单的返回顶部效果的代码实现&#xff0c;附注释说明。 1. 最简单的静态返回顶部&#xff0c;点击直接跳转页面顶部&#xff0c;常见于固定放置在页面底部返回顶部功能 方法一&#xff1a;用命名锚点击返回到顶部预设的id为top的元素 html代码 <a href"#top…

微信公众平台的服务号和订阅号

微信公众平台 服务号 订阅号 作者&#xff1a;方倍工作室 地址&#xff1a;http://www.cnblogs.com/txw1958/p/ServiceNumber-subscriptionNumber.html 什么是服务号&#xff1f; 服务号给企业和组织提供更强大的业务服务与用户管理能力&#xff0c;帮助企业快速实现全新的公众…

Android 第十七课 碎片的简单用法及动态添加碎片

Fragment(碎片)是一种可以嵌入在活动当中的UI片段&#xff0c;它可以让程序更加合理和充分的利用大屏幕的空间。碎片和活动太像了&#xff0c;同样都包含布局&#xff0c;都有自己的声明周期&#xff0c;可以将碎片理解为一种迷你型的活动。 新建FragmentTest项目。假设项目已经…

在Linux下禁用键盘、鼠标、触摸板(笔记本)等输入设备

在Linux系统下禁用键盘、触摸板、鼠标等输入设备&#xff0c;可以通过xinput命令来实现&#xff1a;主要涉及&#xff1a;#xinput list#xinput list-props list-number#xinput set-prop list-number func-number 1/0具体操作如下&#xff1a;step1&#xff1a;查看系统中有那些…

委托又给我惹麻烦了————记委托链的取消注册、获取返回值

今天改bug碰到了一个问题&#xff0c;有多个方法注册到了一个事件里去&#xff0c;而这些方法本身又有点儿互斥&#xff0c;因而造成了bug&#xff0c;哥调试半天才发现&#xff0c;郁闷至极&#xff0c;遂复习了以前的知识并进行适当延伸&#xff0c;再将成果记录及分享之&…

Android 第十八课 强大的滚动控件 RecyclerView

步骤&#xff1a; 一、添加依赖库compilecom.android.support:recyclerview-v7:26.1.0 二、在activity_mian.xml中&#xff0c;添加RecyclerView控件&#xff0c;并占据整个页面。 三、把你要在RecyclerView中展示的内容&#xff0c;设置成一个实体类Fruit&#xff0c;接着为Re…

ios即时通讯客户端开发之-mac上安装MySQL

一、安装 到MySQL官网上http://dev.mysql.com/downloads/mysql/&#xff0c;下载mysql可安装dmg版本 比如&#xff1a;Mac OS X ver. 10.7 (x86, 64-bit), DMG Archive 下载完的文件为&#xff1a;mysql-5.6.10-osx10.7-x86_64.dmg 1.点击&#xff0c;安装包里的 2.点击安装 安…

dbus 和 policykit 实例篇(python)

dbus 和 policykit 实例篇&#xff08;python&#xff09; 使用policykit 的程序一般都有一个dbus daemon程序来完成相关操作&#xff0c;这个dbus daemon 会在系统注册一个system bus 服务名&#xff0c;用于响应要求root privileged的操作&#xff0c;当dbus请求到达时会先验…

和菜鸟一起学linux之DBUS基础学习记录

转自&#xff1a;http://blog.csdn.net/eastmoon502136/article/details/10044993 D-Bus三层架构 D-Bus是一个为应用程序间通信的消息总线系统, 用于进程之间的通信。它是个3层架构的IPC 系统&#xff0c;包括&#xff1a; 1、函数库libdbus &#xff0c;用于两个应用程序互…

Android 第二十课 广播机制(大喇叭)----发送自定义广播(包括发送标准广播和发送有序广播)

广播分为两种类型&#xff1a;标准广播和有序广播 我们来看一下具体这两者的具体区别&#xff1a; 1、发送标准广播 我们需要先定义一个广播接收器来准备接收此广播才行&#xff0c;否则也是白发。 新建一个MyBroadcastReceiver,代码如下&#xff1a; package com.example.broa…

八大排序算法

概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采用…

Android 第二十一课 RecyclerView简单的应用之编写“精美”的聊天页面

1、由于我们会使用到RecyclerView&#xff0c;因此首先需要在app/build.gradle当中添加依赖库。如下&#xff1a; apply plugin: com.android.application .... dependencies {....compile com.android.support:recyclerview-v7:26.1.0 } 2、然后开始编写主页面&#xff0c;修该…

JavaScript 第四课 案例研究:JavaScript图片库

主要内容&#xff1a;编写一个优秀的标记文件编写一个JavaScript函数以显示用户想要查看的内容由标记出发函数调用使用几个新方法扩展这个JavaScript函数 学习过DOM&#xff0c;我们用JavaScript和DOM去建立一个图片库。最好的办法是什么呢&#xff1f; 利用JavaScript来建立图…

windows下mongodb安装与使用整理

一、首先安装mongodb 1.下载地址&#xff1a;http://www.mongodb.org/downloads 2.解压缩到自己想要安装的目录&#xff0c;比如d:\mongodb 3.创建文件夹d:\mongodb\data\db、d:\mongodb\data\log&#xff0c;分别用来安装db和日志文件&#xff0c;在log文件夹下创建一个日志文…

USACO4.12Beef McNuggets(背包+数论)

昨天晚上写的一题 结果USACO一直挂中 今天交了下 有一点点的数论知识 背包很好想 就是不好确定上界 官方题解&#xff1a; 这是一个背包问题。一般使用动态规划求解。 一种具体的实现是&#xff1a;用一个线性表储存所有的节点是否可以相加得到的状态&#xff0c;然后每次可以…

Java 循环语句中 break,continue,return有什么区别?

break 结束循环&#xff0c;跳出循环体,进行后面的程序;continue 结束本次循环&#xff0c;进行下次循环;return 跳出循环体所在的方法&#xff0c;相当于结束该方法; 例子&#xff1a; public class whiletrueTest{public static void main(String[] args) {heihei();haha();…

运算放大器单电源应用中的使用齐纳二极管偏置方法

运算放大器单电源应用中的偏置方法除了使用大电阻使运放输出达到电源电压的一半外&#xff0c;还有使用齐纳二极管&#xff08;稳压管&#xff09;方法也能得到达到应用目的。 下面就推荐几个齐纳二极管&#xff08;分别对应着电源电压是15V,12V&#xff0c;9V;5V&#xff09; …

dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算

本文转自&#xff1a;http://www.cnblogs.com/yaozhongxiao/archive/2014/07/14/3842908.html 一、基本概念 dip &#xff1a; Density independent pixels &#xff0c;设备无关像素。 dp &#xff1a;就是dip px &#xff1a; 像素 dpi &#xf…

Java 集合中关于Iterator 和ListIterator的详解

1.Iterator Iterator的定义如下&#xff1a;public interface Iterator<E> {}Iterator是一个接口&#xff0c;它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下&#xff1a;forEachRemaining(Consumer<? super E> action)&a…