关系型数据库:sql语句:结构化的查询语言
DDL:数据定义语言:
create alter drop
DML:数据操作语言.(数据的增删改)
添加:insert into 表名(字段1,字段2…) values(值1,值2…);
修改:update 表名 set 字段1=值1,字段2=值2 where [条件];
删除:delete from 表名 where 条件
DQL:数据查询语言:
select * from 表名;全查
排序查询:
select * from 表名 order by 排序字段 asc(正序)或desc(倒序)
分组查询:
select * from 表名 group by 字段 having 筛选条件;
子查询:
select * from 表名 where 字段
>(select 字段 from 表名);
多表联查:
自然连接: 表A 表B
select * from A,B wher A.主键=B.外键
自连接:表A
select * from A a,A b where a.主键=B.外键
外连接:表A 表B
左外连接:
select * from A left join B on A.主键=B.外键
右外连接:
select * from B right join A on A.主键=B.外键
内连接:
select * from A inner join B on A.主键=B.外键
DCL:数据控制语言.
数据库的连接语句
Connection conn=null;
public Connection initConnection() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/school?serverTimezone=GMT", "root", "root");
return conn;
}
public void closeConnection() throws Exception{
conn.close();
}
JSON解析
天气界面的实现
1.在.xml文件中将控件摆放好
2.在raw中有json文件中创建天气信息
3.方便使用json中的属性,将其封装为一个类(private 类型 属性,get和set方法)
4.声明、获取控件中的对象;按钮绑定点击事件
//绑定按钮事件
btn_bj.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getMap(1);
}
});
btn_sh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getMap(0);
}
});
btn_gz.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getMap(2);
}
});
}
public void getMap(int i){
//获取集合中对应的集合对象,点击谁获取谁的对象
Weather weather= (Weather) list.get(i);
tv_name.setText(weather.getName());
tv_weather.setText(weather.getWeather());
tv_temp.setText(weather.getTemp());
tv_wind.setText("风力:"+weather.getWind());
tv_pm.setText("PM值:"+weather.getPm());
}
5.获取JSON文件内容进行解析:
private List list;
//获取JSON文件内容进行解析 文件路径
InputStream is=this.getResources().openRawResource(R.raw.weather); //获取JSON文件输入流
try {
//定义输入流每次读取的大小, available()读取输入流的最大程度
byte[] bytes=new byte[is.available()];
is.read(bytes);//输入流开始读取文档信息
String str=new String(bytes,"utf-8"); //字节转换为字符串
//通过fast接送JSON字符串
list= JSON.parseArray(str,Weather.class);
} catch (IOException e) {
e.printStackTrace();
}
获取第三方数据
//封装一个方法,获取网络的第三方数据
public void requestGet(){
//创建一个新的线程,获取第三方数据
new Thread(new Runnable(){
@Override
public void run() {
try {
//声明第三方数据地址:
String str="http://www.foodcredit.org.cn/zs/api/v1/enterprise_code/search?name=";
//网址封装成为地址对象,路径对象
URL url=new URL(str);
//连网打开网络连接:url.openConnection();
HttpURLConnection urlConn= (HttpURLConnection) url.openConnection();
//设置属性,例如:链接主机超时时间,
urlConn.setConnectTimeout(5000);
urlConn.setReadTimeout(5000); //读取文件时间
urlConn.setUseCaches(true); //缓存:true,false
urlConn.setRequestMethod("GET"); //请求方式
//设置(标题head)请求中媒体类型信息(服务器类型)
urlConn.setRequestProperty("Content-Type","application/json"); //客户端与服务器的连接类型
urlConn.addRequestProperty("Connection","Keep-Alive");
//开始连接我们的网络地址,服务器已经构成链接
urlConn.connect();
//判断APP是否请求成功。状态码为200,表示相响应成功
if(urlConn.getResponseCode()==200) {
//获取请求网站的输入流:urlConn.getInputStream();
InputStream is = urlConn.getInputStream();
//定义一个字节输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//读写操作,定义读取长度。声明一个字节数组
byte[] bytes = new byte[1024];
//定义一个变量,代表每次读取的长度
int len = 0;
//开始循环读取数据
while ((len = is.read(bytes))!=-1) {
//把读取到的数据输出到输出流缓冲区
baos.write(bytes, 0, len);
}
//冲刷输出流
baos.flush();
//关闭流。先进后出
baos.close();
is.close();
//把输出流内容转换为字节数组
byte[] bytes1 = baos.toByteArray();
//把字节数组封装为一个字符串
String str1 = new String(bytes1);
//把获取的数据打印到控制台
Log.i("wxy", str1);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();//流异常
}
}
}).start();//开启线程
常用数据适配器
BaseAdapter:
BaseAdapter即基本的适配器,使用BaseAdapter时需要实现四个方法。
SimpleAdapter:
SimpleAdapter继承自BaseAdapter,实现了BaseAdapter的四个抽象方法并进行了封装。
ArrayAdapter:
ArrayAdapter也是BaseAdapter的子类,通常用于适配TextView控件,ArrayAdapter有多个构造方法。
适配器的创建:
private List<NewsInfo> list;
private ListView lv;
//创建适配器
class MyBaseAdapter extends BaseAdapter {
//货物(item)列表项的总数
@Override
public int getCount() {
return list.size();
}
//获取每一个列表项对象
@Override
public Object getItem(int i) {
return list.get(i);
}
//获取每一个列表项下标
@Override
public long getItemId(int i) {
return i;
}
//获取每一个列表项的内容。button在适配器里面实现
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder vh;
//判断视图是否是第一次加载`
if (view == null) { //第一次加载
//把布局文件转化为对象 :
//getApplicationContext():获取服务器环境
//R.layout.news_item:布局文件
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.news_item, null);
//获取组件对象
vh = new ViewHolder();
vh.tv_title = view.findViewById(R.id.tv_title);
vh.tv_content = view.findViewById(R.id.tv_content);
vh.tv_type = view.findViewById(R.id.tv_type);
//把组件对象放到view视图里面
view.setTag(vh);
} else { //不是第一次加载
vh = (ViewHolder) view.getTag();
}
//给组件赋值
vh.tv_title.setText(list.get(i).getTitle() + "");//""将int类型转化为String类型
vh.tv_content.setText(list.get(i).getContent());
//给类型赋值:类型在数据库中是数字,所以要用设置。
int type = list.get(i).getType();
if (type == 1) {
vh.tv_type.setText("评论:" + list.get(i).getComment());
} else if (type == 2) {
vh.tv_type.setText("专题");
} else if (type == 3) {
vh.tv_type.setText("LIVE");
}
return view;
}
//内部类:页面要显示的内容的ID
class ViewHolder {
TextView tv_title;
TextView tv_content;
TextView tv_type;
}
SQLite数据库
简介:
SQLite数据库是一个轻量级的数据库,SQLite是遵循ACID的关系数据库管理系统,没有服务器进程,通过文件保存数据,该文件是跨平台的,处理速度快。
SQLite保存数据时,支持NULL(零)、INTEGER(整数)、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)五种数据类型 。
什么是事务
事务管理是每个数据库(oracle、mysql、db等)都必须实现的。
数据库事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部执行,要么全部不执行。事务特性(4种):
原子性 (atomicity):强调事务的不可分割
一致性 (consistency):事务的执行的前后数据的完整性保持一致
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库
创建:
第一步:创建一个类继承自SQLiteOpenHelper, 在该方法中通过super()调用父类SQLiteOpenHelper的构造方法,并传入4个参数,分别为上下文对象、数据库名称、游标工厂(通常是null)、数据库版本。
//创建数据库的类 继承抽象类,要被重写
public class MyHelper extends SQLiteOpenHelper { //implement两个方法后,报错,缺少构建方法
public Context myContext;//全局变量,
//构造方法,四个参数
//Context:上下文对象;name:数据库文件名称;factory:游标工厂,相当于JAVA集合;version:数据库版本号;
public MyHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
super(context, name,factory, version);
myContext=context;
}
//方法:在数据库第一次创建时会被调用,初始化表格结构
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
//此方法里面构建数据库表格:
//编写创建表格的sql语句:id、name、price
String sql="create table test_db("+"id Integer primary key autoincrement," +
"name varchar(20)," +
"price Integer)";
//执行SQL语句
sqLiteDatabase.execSQL(sql);
//提示语句:
Toast.makeText(myContext,"建表成功!!!",Toast.LENGTH_LONG).show();
}
//数据库版本增加时会被调用
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
对于数据库的可视化可以通过【View】→【Tool Windows】→【Device File Explorer】导出数据库
数据库的使用:
增加一条数据:
//声明一个添加的方法:
public void insertTest(String name,Integer price){
//获取数据
SQLiteDatabase db=dbHelper.getWritableDatabase();
//编写添加的SQL语句
String sql1= "insert into test_db(name,price) values(?,?)";
//执行SQL语句:execSQL()
db.execSQL(sql1,new Object[]{name,price});
//关闭数据库
db.close();
//提示语句:
Toast.makeText(this,"数据添加成功!!!",Toast.LENGTH_LONG).show();
}
//按钮点击事件,添加
btn_insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
insertTest("王豆豆",123);
insertTest1("张晨",555);
}
});
修改 一条记录:
//声明一个修改的方法:
public void updateTest(Integer ID,String name,Integer price){
SQLiteDatabase db=dbHelper.getWritableDatabase();
String sql3="update test_db set name=?,price=? where ID=?";
db.execSQL(sql3,new Object[]{name,price,ID});
db.close();
Toast.makeText(this,"数据修改成功!!!",Toast.LENGTH_LONG).show();
}
btn_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
updateTest(6,"李三",666);
}
});
删除一条数据:
//声明一个删除的方法:
public void deleteTest(Integer ID){
SQLiteDatabase db=dbHelper.getWritableDatabase();
String sql2="delete from test_db where id=?" ;
db.execSQL(sql2,new Object[]{ID});
db.close();
Toast.makeText(this,"数据删除成功!!!",Toast.LENGTH_LONG).show();
}
//根据ID删除
btn_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
deleteTest(2);
}
});
查询数据:
//声明一个查询的方法:
public void selectByID(int ID){
//获取数据库对象
SQLiteDatabase db=dbHelper.getWritableDatabase();
//编写添加的SQL语句
String sql5="select * from test_db where id=?";
//执行SQL语句:
Cursor cursor=db.rawQuery(sql5,new String[]{ID+""});
//判断游标中(1.判断true,false;2.判断长度)
int num=cursor.getCount();
if(num>0){ //查到数据
cursor.moveToFirst();//把游标移动到数据上
Log.i("wxy","\t\n ID:"+cursor.getInt(0) //第一列的数据类型是Int类型
+"\t\n name:"+cursor.getString(1) //第一列的数据类型是String类型
+"\t\n price:"+cursor.getInt(2)
);
}else{ //查不到数据
Log.i("wxy","查无此数据!!"); }
cursor.close();//关闭游标
db.close();//关闭数据库
}
btn_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//获取要查询的条件
String id=et_id.getText().toString().trim(); //trim()去除空格
//把String类型的id转换为int类型
if(id!="" && id!=null){
try {
int idNum=Integer.parseInt(id); //倘若输入的不是数字,报错try_catch
selectByID(idNum);//调用根据id查询的方法:
}catch(Exception e){
Toast.makeText(myContext,"查询ID不是数字",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(myContext,"输入有问题不可查询!",Toast.LENGTH_LONG).show();
}
}});
查询使用的是query()方法,该方法返回的是一个行数集合Cursor。cursor是一个游标接口,提供了遍历查询结果的方法,如指针移动move()方法、moveToNext()。
public boolean find(long id){
SQLiteDatabase db = helper.getReadableDatabase(); //获取可读取的SQLiteDatabase
Cursor cursor = db.query("information", null, "_id=?", new String[]{id+""}, null, null, null);
boolean result = cursor.moveToNext();
cursor.close();
db.close();
return result;
}
query()接收了7个参数:第一个参数表示表名,第二个表示查询的列名,第三个参数接收查询条件子句,第四个接收查询子句对应的条件值,第五个表示分组方式,第六个表示接收having条件(定义组的过滤器),第七个表示排序方式。
BroadcastReceiver(广播接收者)
静态注册:
静态注册就是创建一个广播接收者,并在清单文件中完成注册。
第一步:选择【New】→【Other】→【BroadcastReceiver】
Exported:复选框用于选择是否接收程序之外的广播(默认勾选)
Enabled:用于选择广播接收者是否可以由系统实例化(默认勾选)
//会自动承
public class MyReceiver extends BroadcastReceiver {
//接收到我们的广播之后要执行的内容
@Override
public void onReceive(Context context, Intent intent) {
//当接收到短信的时候要做的事情
Log.i("wxy","我通过广播接收者接收到了一条短信!!!");
}
}
第二步:在清单文件中设置意图过滤器
<!-- 静态注册:无论我们的项目是否启动,广播接收者都会运行 ,自动在清单文件中注册广播接收者-->
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<!-- 设置意图过滤器:就是接受者要接受哪一种广播 -->
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
同时:设置所需要的某种权限
<!--读取手机短信的权限:--><uses-permission android:name="android.permission.RECEIVE_SMS" /><!--设置读取手机通讯录的权限:-->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
动态注册:
创建一个广播接收者,同时在Acitivity中通过代码进行注册(生命周期依赖注册广播的组件)。当Acitivity销毁时,广播接收者也随之被移除。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取短信列表的权限
//检查自身权限,清单文件 如果不存在获取创建
if(ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[] {Manifest.permission.RECEIVE_SMS},1);
}
//实例化广播接收者:
MyReceiver receiver = new MyReceiver();
//声明接收者接收的广播类型:
String action = "android.provider.Telephony.SMS_RECEIVED";
//实例化过滤器:
IntentFilter intentFilter = new IntentFilter(action);
//注册广播:
registerReceiver(receiver,intentfilter);
}
protected void onDestroy() {
super.onDestroy();
//当Acitivity销毁时取消注册BroadcastReceiver
unregisterReceiver(receiver);
}
服务(Service)
服务有两种启动方式:startService( )启动和bindService( )启动
服务在文件清单中会自动注册(如图):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQ1YHIId-1662549465062)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1650204788257.png)]
startService( )启动:
创建一个Service类,重写Service生命周期中的方法
当通过startService( )方法启动服务时,需要自身调用stopSelf( )方法或者其他组件调用stopService( )方法时服务才能停止。
第一步:启动之后先调用onCreate()方法来创建服务;
第二步:调用onStartcommand()执行服务;
第三步:服务运行中;
第四步:调用销毁方法onDestroy()
public MyService() {
}
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
Log.i("wxy","启动服务后,通过onCreate()创建服务!");
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("wxy","startService()启动后,服务要做的事;;;");
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy() {
Log.i("wxy","服务被销毁。。。");
super.onDestroy();
}
在Activity里面进行绑定点击事件:
btn_start=findViewById(R.id.btn_start);
btn_stop=findViewById(R.id.btn_stop);
//绑定点击事件
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建服务
Intent intent=new Intent(MainActivity.this,MyService.class);
startService(intent); //开启服务
}
});
btn_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建服务
Intent intent=new Intent(MainActivity.this,MyService.class);
stopService(intent); //停止服务
}
});
bindService( )启动:
当使用bindService( )方法启动服务时,需要调用onUnbind( )方法解除绑定之后才会被销毁。
第一步:启动之后先调用onCreate()方法来创建服务;
第二步:调用onBind()方法来给服务绑定应用程序;
第三步:客户端(应用程序)在服务中执行;
第四步:销毁服务之前要通过onUnbind()方法解除绑定
第五步:调用onDestroy()销毁方法。
public MyService2() {
}
//创建一个服务的代理类,这个类里面就是要去要做的事情
class MyBinder extends Binder {
//生命绑定的应用程序要做的事情
public void callMethod(){
Log.i("wxy","绑定服务后要做的事情!!!");
}
}
public void onCreate() {
super.onCreate();
}
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public boolean onUnbind(Intent intent) {
Log.i("wxy","服务已无用,onUnbind()解绑服务!!!");
return super.onUnbind(intent);
}
public void onDestroy() {
Log.i("wxy","服务被销毁。。。。。。");
super.onDestroy();
}
在Activity里面进行绑定点击事件:
private MyService2.MyBinder myBinder;
private MyConn myConn;
//绑定服务
public void btnBind(View view){
if(myconn == null){
myconn=new Myconn();
}
Intent intent=new Intent(MainActivity2.this,MyService2.class);
//绑定服务:
//intent:要启动的服务;myConn:链接对象;BIND_AUTO_CREATE:表示如果没有服务自动创建一个。
bindService(intent, myConn, BIND_AUTO_CREATE);
}
//解绑服务
public void btnUnbind(View view){
if(myconn ! == null){
unbindService(myconn);
myconn=new Myconn();
}
}
//调用服务中的方法
public void btnCall(View view){
myBinder.callMethod();
}
//创建MyConn类,用于实现连接服务
private class MyConn implements ServiceConnection{
//会报错,可以生成两个方法:
//当成功绑定到服务时调用的方法,返回MyService里面的Ibinder对象
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
myBinder=(MyService2.MyBinder) iBinder;
Log.i("MainActivity2","服务绑定成功,内存地址为:"+myBinder.toString());
}
//当服务失去连接时调用的两个方法
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
网络编程
HTTP协议:
1.HTTP(Hyper Text Transfer Protocol)即超文本传输协议,它规定了浏览器和服务器之间相互通信的规则。
2.HTTP协议是一种请求/响应式的协议。
当客户端与服务器端建立连接后,向服务器端发送的请求,称作HTTP请求。
当服务器端接收到请求后会做出响应,称为HTTP响应。
四种请求方式:
1、GET请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的。
2、与GET不同的是,PUT请求是向服务器端发送数据的,从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次PUT操作,其结果并没有不同。
3、POST请求同PUT请求类似,都是向服务器端发送数据的,但是该请求会改变数据的种类等资源,就像数据库的insert操作一样,会创建新的内容。几乎目前所有的提交操作都是用POST请求的。
4、DELETE请求顾名思义,就是用来删除某一个资源的,该请求就像数据库的delete操作。
就像前面所讲的一样,既然PUT和POST操作都是向服务器端发送数据的,那么两者有什么区别呢。。。POST主要作用在一个集合资源之上的(url),而PUT主要作用在一个具体资源之上的(url/xxx),通俗一下讲就是,如URL可以在客户端确定,那么可使用PUT,否则用POST。
综上所述,我们可理解为以下:
1、POST /url 创建
2、DELETE /url/xxx 删除
3、PUT /url/xxx 更新
4、GET /url/xxx 查看
访问网络:
实例*
……………………