Android移动开发基础

关系型数据库: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 查看

访问网络:

实例*

……………………

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱尔斯Jules

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值