测试

  • 黑盒测试

    • 测试逻辑业务
  • 白盒测试

    • 测试逻辑方法
  • 根据测试粒度

    • 方法测试:function test
    • 单元测试:unit test
    • 集成测试:integration test
    • 系统测试:system test
  • 根据测试暴力程度

    • 冒烟测试:smoke test
    • 压力测试:pressure test

单元测试junit

  • 定义一个类继承AndroidTestCase,在类中定义方法,即可测试该方法

  • 在指定指令集时,targetPackage指定你要测试的应用的包名

      <instrumentation android:name="android.test.InstrumentationTestRunner"android:targetPackage="com.itheima.junit"></instrumentation>
    
  • 定义使用的类库

      <uses-library android:name="android.test.runner"></uses-library>
    
  • 断言的作用,检测运行结果和预期是否一致

  • 如果应用出现异常,会抛给测试框架


SQLite数据库

  • 轻量级关系型数据库
  • 创建数据库需要使用的api:SQLiteOpenHelper
    • 必须定义一个构造方法:

        //arg1:数据库文件的名字//arg2:游标工厂//arg3:数据库版本public MyOpenHelper(Context context, String name, CursorFactory factory, int version){}
      
    • 数据库被创建时会调用:onCreate方法

    • 数据库升级时会调用:onUpgrade方法

创建数据库

//创建OpenHelper对象
MyOpenHelper oh = new MyOpenHelper(getContext(), "person.db", null, 1);
//获得数据库对象,如果数据库不存在,先创建数据库,后获得,如果存在,则直接获得
SQLiteDatabase db = oh.getWritableDatabase();
  • getWritableDatabase():打开可读写的数据库

  • getReadableDatabase():在磁盘空间不足时打开只读数据库,否则打开可读写数据库

  • 在创建数据库时创建表

      public void onCreate(SQLiteDatabase db) {// TODO Auto-generated method stubdb.execSQL("create table person (_id integer primary key autoincrement, name char(10), phone char(20), money integer(20))");}
    

数据库的增删改查

###SQL语句

  • insert into person (name, phone, money) values (‘张三’, ‘159874611’, 2000);
  • delete from person where name = ‘李四’ and _id = 4;
  • update person set money = 6000 where name = ‘李四’;
  • select name, phone from person where name = ‘张三’;

执行SQL语句实现增删改查

 //插入db.execSQL("insert into person (name, phone, money) values (?, ?, ?);", new Object[]{"张三", 15987461, 75000});//查找Cursor cs = db.rawQuery("select _id, name, money from person where name = ?;", new String[]{"张三"});
  • 测试方法执行前会调用此方法

      protected void setUp() throws Exception {super.setUp();//                    获取虚拟上下文对象oh = new MyOpenHelper(getContext(), "people.db", null, 1);}
    

使用api实现增删改查

  • 插入

      //以键值对的形式保存要存入数据库的数据ContentValues cv = new ContentValues();cv.put("name", "刘能");cv.put("phone", 1651646);cv.put("money", 3500);//返回值是改行的主键,如果出错返回-1long i = db.insert("person", null, cv);
    
  • 删除

      //返回值是删除的行数int i = db.delete("person", "_id = ? and name = ?", new String[]{"1", "张三"});
    
  • 修改

      ContentValues cv = new ContentValues();cv.put("money", 25000);int i = db.update("person", cv, "name = ?", new String[]{"赵四"});
    
  • 查询

      //arg1:要查询的字段//arg2:查询条件//arg3:填充查询条件的占位符Cursor cs = db.query("person", new String[]{"name", "money"}, "name = ?", new String[]{"张三"}, null, null, null);while(cs.moveToNext()){//                            获取指定列的索引值String name = cs.getString(cs.getColumnIndex("name"));String money = cs.getString(cs.getColumnIndex("money"));System.out.println(name + ";" + money);}
    

事务

  • 保证多条SQL语句要么同时成功,要么同时失败

  • 最常见案例:银行转账

  • 事务api

      try {//开启事务db.beginTransaction();...........//设置事务执行成功db.setTransactionSuccessful();} finally{//关闭事务//如果此时已经设置事务执行成功,则sql语句生效,否则不生效db.endTransaction();}
    

MyOpenHelper.java

package com.example.administrator.myapplication;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;public class MyOpenHelper extends SQLiteOpenHelper {public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,int version) {super(context, name, factory, version);// TODO Auto-generated constructor stub}//数据库创建时,此方法会调用@Overridepublic void onCreate(SQLiteDatabase db) {System.out.println("数据库创建了");//创建表db.execSQL("create table person(_id integer primary key autoincrement, name char(10), salary char(20), phone integer(20))");}//数据库升级时,此方法会调用@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {System.out.println("数据库升级了");}}

MainActivity.java

package com.example.administrator.myapplication;import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//getContext():获取一个虚拟的上下文
//        MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);//如果数据库不存在,先创建数据库,再获取可读可写的数据库对象,如果数据库存在,就直接打开
//        SQLiteDatabase db = oh.getWritableDatabase();//如果存储空间满了,那么返回只读数据库对象
//      SQLiteDatabase db = oh.getReadableDatabase();
//        insert();select();
//        insertApi();deleteApi();}public void insert(){//getContext():获取一个虚拟的上下文MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();db.execSQL("insert into person (name,salary,phone) values(?,?,?)", new Object[]{"小志", 14000, "13888"});db.execSQL("insert into person (name,salary,phone) values(?,?,?)",new Object[]{"小智","13000","13888888888"});//SQLSite是轻量级数据库,数据类型错误也能正常插入,全部都认为是字符串,但是插入String到Integer会变成0db.execSQL("insert into person (name,salary,phone) values(?,?,?)",new Object[]{"小刚",13000,"13888888888"});db.close();}public void delete(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();db.execSQL("delete from person where name =?",new Object[]{"小志"});db.close();}public void update(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();db.execSQL("update person set phone = ? where name = ?",new Object[]{"小智","13202120201"});db.close();}public void select(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();Cursor cursor = db.rawQuery("select name,phone,salary from person",null);while (cursor.moveToNext()){String name = cursor.getString(0);String salary = cursor.getString(2);String phone = cursor.getString(cursor.getColumnIndex("phone"));System.out.println(name+";"+salary+";"+phone);}db.close();}public void insertApi(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();ContentValues values = new ContentValues();values.put("name","游戏王");values.put("phone","1952123121");values.put("salary",16000);db.insert("person",null,values);db.close();}public void deleteApi(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();int i = db.delete("person","name=? and _id=?",new String[]{"小刚","7"});System.out.println(i);db.close();}public void updateApi(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();ContentValues values = new ContentValues();values.put("salary",36000);int i = db.update("person",values,"name=?",new String[]{"小刚"});System.out.println(i);db.close();}public void selectApi(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();Cursor cursor = db.query("person",null,null,null,null,null,null,null);while (cursor.moveToNext()){String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));System.out.println(name+":"+phone);}db.close();}public void testTransaction(){MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();//开启事务try{db.beginTransaction();ContentValues values = new ContentValues();values.put("salary",15000);db.update("person",values,"name=?",new String[]{"小智"});values.clear();values.put("salary",13000);db.update("person",values,"name=?",new String[]{"小志"});//这里做一个运行时异常int i = 3/0;//设置事务执行成功db.setTransactionSuccessful();}catch (Exception e){e.printStackTrace();}finally {//关闭事务,同时提交,如果没有设置事务执行成功则sql回滚db.endTransaction();db.close();}}}




把数据库的数据显示至屏幕

  1. 任意插入一些数据
  • 定义业务bean:Person.java

  • 读取数据库的所有数据

     Cursor cs = db.query("person", null, null, null, null, null, null);while(cs.moveToNext()){String name = cs.getString(cs.getColumnIndex("name"));String phone = cs.getString(cs.getColumnIndex("phone"));String money = cs.getString(cs.getColumnIndex("money"));//把读到的数据封装至Person对象Person p = new Person(name, phone, money);//把person对象保存至集合中people.add(p);}
    
  • 把集合中的数据显示至屏幕

       LinearLayout ll = (LinearLayout) findViewById(R.id.ll);for(Person p : people){//创建TextView,每条数据用一个文本框显示TextView tv = new TextView(this);tv.setText(p.toString());//把文本框设置为ll的子节点ll.addView(tv);}
    
  • 分页查询

      Cursor cs = db.query("person", null, null, null, null, null, null, "0, 10");
    

activity_main.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/ll"android:layout_width="match_parent"android:layout_height="wrap_content"tools:context=".MainActivity"android:orientation="vertical"></LinearLayout>
</ScrollView>

MainActivity.java

package com.example.administrator.myapplication;import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.administrator.myapplication.domain.Person;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private List<Person> personList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);personList = new ArrayList<>();MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();Cursor cursor = db.query("person",null,null,null,null,null,null,null);while (cursor.moveToNext()){String _id = cursor.getString(cursor.getColumnIndex("_id"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));String salary = cursor.getString(cursor.getColumnIndex("salary"));Person person = new Person(_id,name,phone,salary);personList.add(person);}db.close();LinearLayout ll = findViewById(R.id.ll);//把数据显示至屏幕for(Person person:personList){TextView tv = new TextView(this);tv.setText(person.toString());//把TextView设置为线性布局的子节点tv.setTextSize(18); //18spll.addView(tv);}}
}

效果演示


ListView

  • 就是用来显示一行一行的条目的
  • MVC结构
    • M:model模型层,要显示的数据 ————people集合
    • V:view视图层,用户看到的界面 ————ListView
    • c:control控制层,操作数据如何显示 ————adapter对象
  • 每一个条目都是一个View对象

BaseAdapter

  • 必须实现的两个方法

    • 第一个

        //系统调用此方法,用来获知模型层有多少条数据@Overridepublic int getCount() {return people.size();}
      
    • 第二个

        //系统调用此方法,获取要显示至ListView的View对象//position:是return的View对象所对应的数据在集合中的位置@Overridepublic View getView(int position, View convertView, ViewGroup parent) {System.out.println("getView方法调用" + position);TextView tv = new TextView(MainActivity.this);//拿到集合中的元素Person p = people.get(position);tv.setText(p.toString());//把TextView的对象返回出去,它会变成ListView的条目return tv;}
      
  • 屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕

activity_main.xml

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/ll"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent"></ListView>
</LinearLayout>

MainActivity.java

package com.example.administrator.myapplication;import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.example.administrator.myapplication.domain.Person;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private List<Person> personList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);personList = new ArrayList<>();MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();Cursor cursor = db.query("person",null,null,null,null,null,null,null);while (cursor.moveToNext()){String _id = cursor.getString(cursor.getColumnIndex("_id"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));String salary = cursor.getString(cursor.getColumnIndex("salary"));Person person = new Person(_id,name,phone,salary);personList.add(person);}db.close();ListView lv = findViewById(R.id.lv);lv.setAdapter(new MyAdapter());}class MyAdapter extends BaseAdapter{@Overridepublic int getCount() {return personList.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {TextView tv = new TextView(MainActivity.this);Person p =personList.get(position);tv.setTextSize(18);tv.setText(p.toString());return tv;}}
}

为了显示好看一点

item_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><TextView android:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="名字"android:textSize="25sp"/><LinearLayout android:layout_alignParentRight="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><TextView android:id="@+id/tv_phone"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="号码"/><TextView android:id="@+id/tv_salary"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="工资"/></LinearLayout>
</RelativeLayout>

MainActivity.java

package com.example.administrator.myapplication;import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.example.administrator.myapplication.domain.Person;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private List<Person> personList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);personList = new ArrayList<>();MyOpenHelper oh = new MyOpenHelper(getApplicationContext(),"people.db", null, 1);SQLiteDatabase db = oh.getWritableDatabase();Cursor cursor = db.query("person",null,null,null,null,null,null,null);while (cursor.moveToNext()){String _id = cursor.getString(cursor.getColumnIndex("_id"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));String salary = cursor.getString(cursor.getColumnIndex("salary"));Person person = new Person(_id,name,phone,salary);personList.add(person);}db.close();ListView lv = findViewById(R.id.lv);lv.setAdapter(new MyAdapter());}class MyAdapter extends BaseAdapter{@Overridepublic int getCount() {return personList.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Person p =personList.get(position);View view = View.inflate(MainActivity.this,R.layout.item_listview,null);TextView tv_name = view.findViewById(R.id.tv_name);tv_name.setText(p.getName());TextView tv_phone = view.findViewById(R.id.tv_phone);tv_phone.setText("手机号:"+p.getPhone());TextView tv_salary =view.findViewById(R.id.tv_salary);tv_salary.setText("工资:"+p.getSalary());return view;}}

条目的缓存

  • 当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存

对话框

确定取消对话框

  • 创建对话框构建器对象,类似工厂模式

  •   AlertDialog.Builder builder = new Builder(this);
    
  • 设置标题和正文

  •   builder.setTitle("警告");builder.setMessage("若练此功,必先自宫");
    
  • 设置确定和取消按钮

      builder.setPositiveButton("现在自宫", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "恭喜你自宫成功,现在程序退出", 0).show();}});builder.setNegativeButton("下次再说", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "若不自宫,一定不成功", 0).show();}});
    
  • 使用构建器创建出对话框对象

      AlertDialog ad = builder.create();ad.show();
    

单选对话框

 AlertDialog.Builder builder = new Builder(this);builder.setTitle("选择你的性别");
  • 定义单选选项
  •   final String[] items = new String[]{"男", "女", "其他"};//-1表示没有默认选择//点击侦听的导包要注意别导错builder.setSingleChoiceItems(items, -1, new OnClickListener() {//which表示点击的是哪一个选项@Overridepublic void onClick(DialogInterface dialog, int which) {Toast.makeText(MainActivity.this, "您选择了" + items[which], 0).show();//对话框消失dialog.dismiss();}});builder.show();
    

多选对话框

 AlertDialog.Builder builder = new Builder(this);builder.setTitle("请选择你认为最帅的人");
  • 定义多选的选项,因为可以多选,所以需要一个boolean数组来记录哪些选项被选了
  •   final String[] items = new String[]{"赵帅哥","赵师哥","赵老师","侃哥"};//true表示对应位置的选项被选了final boolean[] checkedItems = new boolean[]{true,false,false,false,};builder.setMultiChoiceItems(items, checkedItems, new OnMultiChoiceClickListener() {//点击某个选项,如果该选项之前没被选择,那么此时isChecked的值为true@Overridepublic void onClick(DialogInterface dialog, int which, boolean isChecked) {checkedItems[which] = isChecked;}});builder.setPositiveButton("确定", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {StringBuffer sb = new StringBuffer();for(int i = 0;i < items.length; i++){sb.append(checkedItems[i] ? items[i] + " " : "");}Toast.makeText(MainActivity.this, sb.toString(), 0).show();}});builder.show();
    

Android入门笔记03相关推荐

  1. Android入门笔记之更改手机屏幕方向

    Android入门笔记之更改手机屏幕方向 <1>简介 通过一个按钮组来改变横屏竖屏显示. <2>关键步骤 主要通过android.app.activity.getRequest ...

  2. gif透明背景动画_iPad Procreate入门笔记03 - GIF动画制作

    更新至Procreate 5 后,新增加了"动画辅助(animation assist)"功能,制作动画更加容易上手且方便了. 下面介绍几种简单的制作方法. 1. GIF最佳画布大 ...

  3. 使用pil读取gif图有些位置为黑色_iPad Procreate入门笔记03 - GIF动画制作

    更新至Procreate 5 后,新增加了"动画辅助(animation assist)"功能,制作动画更加容易上手且方便了. 下面介绍几种简单的制作方法. 1. GIF最佳画布大 ...

  4. ESP32 入门笔记03:PWM (ESP32 for Arduino IDE)

    先导知识 ESP32 入门笔记01:开发板信息.开发环境搭建以及学资料准备 ESP32 入门笔记02: GPIO参考指南 ESP32 有一个 LED PWM 控制器,具有 16 个独立通道,可配置为生 ...

  5. STM32入门笔记(03):系统时钟控制 RCC (STM32CubeMx 初始化配置)

    目的/起源: B站@立邦大侠 的在视频里面提到,他用STM32CubeMx 更清晰地进行STM32系统时钟配置以及时钟架构. STM32 开发流程 : 芯片选型 - 原理图设计 - PCBlayout ...

  6. Cookie和Session-学习笔记03【Session快速入门、Session细节】

    Java后端 学习路线 笔记汇总表[黑马程序员] Cookie和Session-学习笔记01[Cookie_快速入门.Cookie_细节] Cookie和Session-学习笔记02[Cookie案例 ...

  7. Android Studio 基础入门笔记

    Android Studio 基础入门笔记 Android Studio 基础入门笔记 为什么选择使用 Android Studio 而不是EclipseADT 安卓配置JDK AS如何更新 常规的 ...

  8. Android 插件化原理入门笔记

    Android开发笔记 onGithub 笔记,参考7.2中所列参考文章所写,DEMO地址在PluginTestDemoApplication 1.综述 2015年是Android插件化技术突飞猛进的 ...

  9. Android入门自学笔记

    Android入门 前几个月要去作物联网项目,花了一个月入门android本文写于物联网大赛后 Android入门所需书籍 <android第一行代码>-----入门必看书.这本书实例和理 ...

  10. SpringMVC-学习笔记03【SpringMVC常用注解】

    Java后端 学习路线 笔记汇总表[黑马程序员] SpringMVC-学习笔记01[SpringMVC概述及入门案例][day01] SpringMVC-学习笔记02[参数绑定及自定义类型转换] Sp ...

最新文章

  1. java equal hashcode_Java(二)equal 和 hashcode使用
  2. springMVC 拦截器
  3. 你管这破玩意叫 RDB
  4. ModelSim之命令行仿真入门 (step 2)
  5. C++ GUI Qt4编程(12)-6.1FindFileDialog
  6. 阿加莎•克里斯蒂作品04东方快车谋杀案
  7. 夺命雷公狗---微信开发39----微信语言识别接口1
  8. 消息队列 应用场景 解析
  9. C++ 重载赋值运算符
  10. linux 快速切换ip,linux-如何快速替换IP
  11. Filebeat 收集日志的那些事儿
  12. css代码总结,css属性代码大全总结(一)
  13. java盘点系统_2020年度综合大盘点:火爆IT业的7大Java技术,任何一项都是“卧槽牛逼”!...
  14. PCB的制作工艺流程
  15. php ipa下载 解码,ipa下载的方法
  16. 文档已完成加载后执行document write整个 HTML 页面将被覆盖
  17. 51单片机内部外设:实时时钟(SPI)
  18. Android 智能硬件的理解(2018.5.25)
  19. 关于DBSCAN图像上小圆圈和大圆圈的问题
  20. 7-4 宿舍谁最高? (20 分) map+结构体的应用

热门文章

  1. android adb.exe端口占用
  2. java编程——图片旋转
  3. linker command failed with exit code 1
  4. Android远程推送笔记
  5. 好好学习,好好Show
  6. Asp.net页面传值
  7. ESRI ArcGIS 9.0系列软件报价
  8. 随笔第一天:德语谚语
  9. JMeter数据库操作详解
  10. 数据结构与算法系列----字典树