zoukankan      html  css  js  c++  java
  • 第八章:android应用

    安卓应用

    一、安卓存储-sqllite数据库

    1、使用sql语句对数据库进行增删改查
    • MainActivity
    public class MainActivity extends AppCompatActivity {
        private MyOpenHelper myOpenHelper;
        private TextView tv;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            /**
             * 当数据库不存在时,SQLiteOpenHelper实例调用getWritableDatabase()或getReadableDatabase()会创建数据库,
             * 当数据库存在时则返回数据库实例(SQLiteDatabase)。
             */
            // 创建位置/data/data/com.wuxi.myandroid/databases/
            myOpenHelper = new MyOpenHelper(getApplicationContext());
            tv = findViewById(R.id.tv);
        }
    
        public void insertHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            db.execSQL("insert into person(name,age) values(?,?)", new Object[]{"孟美岐", 18});
            db.close();
        }
    
        public void deleteHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            db.execSQL("delete from person where name=?", new Object[]{"孟美岐"});
            db.close();
        }
    
        public void updateHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            db.execSQL("update person set age=? where name=?", new Object[]{19, "孟美岐"});
            db.close();
        }
    
        public void selectHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getReadableDatabase();
            Cursor cursor = db.rawQuery("select * from person", null);
            StringBuffer sb = new StringBuffer();
            sb.append("[");
            if (cursor != null && cursor.getCount() > 0) {
                boolean first = true;
                while (cursor.moveToNext()) {
                    if (first) {
                        first = false;
                        sb.append("{id:");
                    } else {
                        sb.append(",{id:");
                    }
                    sb.append(cursor.getInt(0))
                            .append(",name:").append(cursor.getString(1))
                            .append(",age:").append(cursor.getInt(2)).append("}");
                }
            }
            sb.append("]");
            tv.setText(sb);
            db.close();
        }
    }
    
    • MyOpenHelper
    public class MyOpenHelper extends SQLiteOpenHelper {
        /**
         * super()参数2:为数据库名称
         * super()参数4:为数据库版本,修改此参数后,会执行onUpgrade()
         */
        public MyOpenHelper(Context context) {
            super(context, "wuxi.db", null, 2);
        }
    
        /**
         * 只在数据库创建时调用一次,适合做表结构初始化操作
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("create table person(_id integer primary key autoincrement,name varchar(20))");
        }
    
        /**
         * 修改数据库版本后会执行此方法,适合做修改数据库表结构操作
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("alter table person add age integer");
        }
    }
    
    2、使用谷歌封装好的api对数据库增删改查
    public class MainActivity extends AppCompatActivity {
        private MyOpenHelper myOpenHelper;
        private TextView tv;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            myOpenHelper = new MyOpenHelper(getApplicationContext());
            tv = findViewById(R.id.tv);
        }
    
        public void insertHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("name", "黄婷婷");
            values.put("age", 20);
            // 返回值为插入数据行的id
            long id = db.insert("person", null, values);
            Log.e("", String.valueOf(id));
            db.close();
        }
    
        public void deleteHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            // 返回值为删除的行数
            int num = db.delete("person", "name=?", new String[]{"黄婷婷"});
            Log.e("", String.valueOf(num));
            db.close();
        }
    
        public void updateHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("age", 21);
            // 返回值为修改的行数
            int num = db.update("person", values, "name=?", new String[]{"黄婷婷"});
            Log.e("", String.valueOf(num));
            db.close();
        }
    
        public void selectHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getReadableDatabase();
            // 参数2为null:查询所有字段;
            // 参数3和4为null:查询所有数据;
            Cursor cursor = db.query("person", new String[]{"_id", "name", "age"}, "name=?", new String[]{"黄婷婷"}, null, null, null);
            StringBuffer sb = new StringBuffer();
            sb.append("[");
            if (cursor != null && cursor.getCount() > 0) {
                boolean first = true;
                while (cursor.moveToNext()) {
                    if (first) {
                        first = false;
                        sb.append("{id:");
                    } else {
                        sb.append(",{id:");
                    }
                    sb.append(cursor.getInt(0))
                            .append(",name:").append(cursor.getString(1))
                            .append(",age:").append(cursor.getInt(2)).append("}");
                }
            }
            sb.append("]");
            tv.setText(sb);
            db.close();
        }
    }
    
    3、Android中数据库事务的介绍
    public class MainActivity extends AppCompatActivity {
        private MyOpenHelper myOpenHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            myOpenHelper = new MyOpenHelper(getApplicationContext());
        }
    
        public void insertHandler(View view) {
            SQLiteDatabase db = myOpenHelper.getWritableDatabase();
            db.beginTransaction();//开启事务
            try {
                db.execSQL("update person set age=? where name=?", new Object[]{20, "孟美岐"});
                int i = 10 / 0;
                db.execSQL("update person set age=? where name=?", new Object[]{21, "黄婷婷"});
                db.setTransactionSuccessful();//事务成功标记
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                db.endTransaction();//根据成功标记决定是否回滚,并关闭事务
            }
            db.close();
        }
    }
    

    二、HttpURLConnection

    1、请求、响应和更新视图
    • 添加权限
    <uses-permission android:name="android.permission.INTERNET" />
    
    • MainActivity
    public class MainActivity extends AppCompatActivity {
        private EditText et;
        private TextView tv;
        private Handler handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message msg) {
                // 1、Toast也必须在主线程绘制UI;2、可根据what属性判断状态。
                switch (msg.what) {
                    case 200:
                        String content = (String) msg.obj;
                        tv.setText(content);
                        break;
                    case 400:
                        Toast.makeText(getApplicationContext(), (String) msg.obj, Toast.LENGTH_SHORT).show();
                        break;
                }
                return false;
            }
        });
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            et = findViewById(R.id.et);
            tv = findViewById(R.id.tv);
        }
    
        /**
         * 1、不能在主线程发送请求
         * 2、只有在主线程才能更新UI
         */
        public void search(View view) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        /**
                         * POST请求方式:
                         * String path = "https://mock.mengxuegu.com/mock/604ac67cf340b05bceda3ee2/sso/auth/login";
                         * // 解决乱码问题
                         * String data = "username=" + URLEncoder.encode("用户名", "utf-8") + "&password=" + URLEncoder.encode("密码", "utf-8");
                         * URL url = new URL(path);
                         * HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                         * conn.setRequestMethod("POST");//要求大写,默认就是GET
                         * conn.setConnectTimeout(5000);
                         * conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                         * conn.setRequestProperty("Content-Length", data.length() + "");
                         * conn.setDoOutput(true);
                         * conn.getOutputStream().write(data.getBytes());
                         * int code = conn.getResponseCode();
                         */
                        String path = et.getText().toString().trim();
                        URL url = new URL(path);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod("GET");//要求大写,默认就是GET
                        conn.setConnectTimeout(5000);
                        int code = conn.getResponseCode();
                        if (code == 200) {
                            InputStream in = conn.getInputStream();
                            String content = StreamUtils.readStream(in);
                            Message msg = Message.obtain();// 从消息池获取对象,效率比new Message()高
                            msg.what = 200;
                            msg.obj = content;
                            handler.sendMessage(msg);
                        }
                    } catch (Exception e) {
                        Message msg = Message.obtain();
                        msg.what = 400;
                        msg.obj = e.getMessage();
                        handler.sendMessage(msg);
                    }
                }
            }).start();
        }
    }
    
    • activity_main.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <EditText
                android:id="@+id/et"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:singleLine="true"
                android:text="https://www.baidu.com" />
    
            <Button
                android:id="@+id/btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="search"
                android:text="搜索" />
        </LinearLayout>
    
        <!--ScrollView只能有一个子节点-->
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </ScrollView>
    </LinearLayout>
    
    • StreamUtils
    public class StreamUtils {
        public static String readStream(InputStream in) throws Exception {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = in.read(bytes)) != -1) {
                baos.write(bytes, 0, len);
            }
            in.close();
            return baos.toString();
        }
    }
    
    2、处理图片资源和资源缓存
    public class MainActivity extends AppCompatActivity {
        private EditText et;
        private ImageView iv;
        private Handler handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message msg) {
                Bitmap bitmap = (Bitmap) msg.obj;
                iv.setImageBitmap(bitmap);
                return false;
            }
        });
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            et = findViewById(R.id.et);
            iv = findViewById(R.id.iv);
        }
    
        public void search(View view) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        /**
                         * 1、getCacheDir()目录地址:/data/data/包名/cache;
                         * 2、用户可通过清空缓存方式清空此目录数据
                         */
                        String path = et.getText().toString().trim();
                        // UUID.nameUUIDFromBytes(byte[]):参数一致,输出的UUID也一致
                        String filename = String.valueOf(UUID.nameUUIDFromBytes(path.getBytes()));
                        Log.e("红色日志--->", filename);
                        // 文件名过长会报错
                        File file = new File(getCacheDir(), filename);
                        if (file.exists() && file.length() > 0) {
                            Log.e("红色日志--->", "使用缓存图片");
                            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                            Message msg = Message.obtain();
                            msg.obj = bitmap;
                            handler.sendMessage(msg);
                        } else {
                            Log.e("红色日志--->", "第一次访问连接网络");
                            URL url = new URL(path);
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            conn.setRequestMethod("GET");
                            conn.setConnectTimeout(5000);
                            int code = conn.getResponseCode();
                            if (code == 200) {
                                InputStream in = conn.getInputStream();
                                FileOutputStream fos = new FileOutputStream(file);
                                int len = 0;
                                byte[] bytes = new byte[1024];
                                while ((len = in.read(bytes)) != -1) {
                                    fos.write(bytes, 0, len);
                                }
                                fos.close();
                                in.close();
                                Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                                Message msg = Message.obtain();
                                msg.obj = bitmap;
                                handler.sendMessage(msg);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    3、runOnUiThread
    public class MainActivity extends AppCompatActivity {
        private EditText et;
        private TextView tv;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            et = findViewById(R.id.et);
            tv = findViewById(R.id.tv);
        }
    
        public void search(View view) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        String path = et.getText().toString().trim();
                        URL url = new URL(path);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod("GET");
                        conn.setConnectTimeout(5000);
                        int code = conn.getResponseCode();
                        if (code == 200) {
                            InputStream in = conn.getInputStream();
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            int len = 0;
                            byte[] bytes = new byte[1024];
                            while ((len = in.read(bytes)) != -1) {
                                baos.write(bytes, 0, len);
                            }
                            in.close();
                            // 不管在什么位置调用都将运行在UI线程里
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv.setText(baos.toString());
                                }
                            });
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    4、其他常见消息api
    public class MainActivity extends AppCompatActivity {
        private TextView tv;
        private Timer timer;
        private TimerTask task;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            tv = findViewById(R.id.tv);
    
            /*
            // 3秒后执行run方法
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    tv.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                }
            }, 3000);
            */
    
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        }
                    });
                }
            };
            // 3秒后,每隔1秒执行一次run方法
            timer.schedule(task, 3000, 1000);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            timer.cancel();
            task.cancel();
        }
    }
    
    5、多线程下载和断点续传
    • 权限
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
    • MainActivity
    public class MainActivity extends AppCompatActivity {
        private String path = "https://www.dingcaiyan.com/lantern-installer.exe";
        private final int threadCount = 3;// 下载开启的线程
        private int runningThread;// 代表当前正在运行的线程
        private LinearLayout ll;
        private ArrayList<ProgressBar> pbList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ll = findViewById(R.id.ll);
            pbList = new ArrayList<ProgressBar>();
        }
    
        private class DownLoadThread extends Thread {
            private int startIndex;
            private int endIndex;
            private int threadId;
            private int pbMaxSize;// 进度条最大值
            private int pbLastPosition;// 进度条断点位置
    
            public DownLoadThread(int startIndex, int endIndex, int threadId) {
                this.startIndex = startIndex;
                this.endIndex = endIndex;
                this.threadId = threadId;
            }
    
            @Override
            public void run() {
                try {
                    pbMaxSize = endIndex - startIndex;
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    /**
                     * 实现断点续传逻辑
                     */
                    // a、获取已下载的大小信息
                    File file = new File(getFilename(path) + threadId + ".txt");
                    if (file.exists() && file.length() > 0) {
                        FileInputStream fis = new FileInputStream(file);
                        BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
                        int lastPosition = Integer.parseInt(bufr.readLine());
                        pbLastPosition = lastPosition - startIndex;
                        startIndex = lastPosition + 1;
                        fis.close();
                    }
                    conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                    int code = conn.getResponseCode();
                    // 206(http状态码):服务器已经成功处理了部分GET请求,该请求必须包含Range头信息来指示客户端希望得到的内容范围,并且可能包含If-Range来作为请求条件。
                    if (code == 206) {
                        RandomAccessFile raf = new RandomAccessFile(getFilename(path), "rw");
                        raf.seek(startIndex);
                        InputStream in = conn.getInputStream();
                        byte[] bytes = new byte[1024 * 1024];
                        int len = 0;
                        // b、存储已下载的大小信息
                        int total = 0;
                        while ((len = in.read(bytes)) != -1) {
                            raf.write(bytes, 0, len);
                            total += len;
                            int currentThreadPosition = startIndex + total;
                            // rwd模式:要求对文件内容的每个更新都同步写入到底层存储设备
                            RandomAccessFile rafPosition = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd");
                            rafPosition.write(String.valueOf(currentThreadPosition).getBytes());
                            rafPosition.close();
                            // 与进度相关的控件都可以在子线程直接更新UI
                            pbList.get(threadId).setMax(pbMaxSize);
                            pbList.get(threadId).setProgress(pbLastPosition + total);
                        }
                        raf.close();
                        // c、删除存储的信息
                        synchronized (DownLoadThread.class) {
                            runningThread--;
                            if (runningThread == 0) {
                                for (int i = 0; i < threadCount; i++) {
                                    File deleteFile = new File(getFilename(path) + i + ".txt");
                                    deleteFile.delete();
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public void submit(View view) {
            ll.removeAllViews();
            pbList.clear();
            for (int i = 0; i < threadCount; i++) {
                ProgressBar progressbar = (ProgressBar) View.inflate(getApplicationContext(), R.layout.progressbar_item, null);
                pbList.add(progressbar);
                ll.addView(progressbar);
            }
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        /**
                         * 实现多线程下载逻辑
                         */
                        // 1、获取网络连接
                        URL url = new URL(path);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod("GET");
                        conn.setConnectTimeout(5000);
                        int code = conn.getResponseCode();
                        if (code == 200) {
                            runningThread = threadCount;
                            // 2、本地磁盘创建相同大小的空文件
                            int fileSize = conn.getContentLength();
                            RandomAccessFile raf = new RandomAccessFile(getFilename(path), "rw");
                            raf.setLength(fileSize);
                            // 3、计算每条线程需从文件哪个部分开始下载,结束
                            int blockSize = fileSize / threadCount;
                            for (int i = 0; i < threadCount; i++) {
                                int startIndex = i * blockSize;
                                int endIndex;
                                if (i == threadCount - 1) {
                                    endIndex = fileSize - 1;
                                } else {
                                    endIndex = (i + 1) * blockSize - 1;
                                }
                                // 4、依次创建,启动多条线程来下载网络资源的指定部分
                                DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i);
                                downLoadThread.start();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        public String getFilename(String path) {
            int start = path.lastIndexOf("/") + 1;
            String substring = path.substring(start);
            return Environment.getExternalStorageDirectory().getPath() + "/" + substring;
        }
    }
    
    • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical">
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="submit"
            android:text="下载" />
    
        <LinearLayout
            android:id="@+id/ll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" />
    
    </LinearLayout>
    
    • progressbar_item.xml
    <?xml version="1.0" encoding="utf-8"?>
    <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
  • 相关阅读:
    [t]淘宝幻灯片上下滑动效果
    [t]手风琴效果
    [t]仿FLASH的图片轮换效果
    [t]新浪微博自动加载信息
    图片加载问题
    [t]照片墙
    Best Of My Renderings
    My car renderings
    Silverlight后台CS代码中创建四种常用的动画效果
    Silverlight、SVG、WPF转换工具
  • 原文地址:https://www.cnblogs.com/linding/p/15739686.html
Copyright © 2011-2022 走看看