Android Studio开发实用notebook

Android Studio实用notebook

  • 《第一行代码待学习/参考知识点》
  • 常用控件
      • API版本问题:源码的编译环境版本不对导致编译错误
      • 【EditText 】
      • 【Button】
      • 【Toast】
      • 【ImageView】
      • 【menu】
      • 【intent】
      • 【ProgressDialog】
      • 【AlertDialog】
      • 【Spiner】下拉选择框
      • 【Activity】使用方法:把以下代码添加到事件中
      • 【ListView】
      • 【读写文件操作】
      • 【SQLite 增删改查】
      • 线程

《第一行代码待学习/参考知识点》

  1. p63,活动的状态(运行、暂停、停止、销毁)、7种回调方法对应3种生存期(完整生存期、可见生存期、前台生存期)
  2. P81改写默认的类,类A继承B,设置C继承B,修改C,让A继承B,即可,可达到自动log.D啊,截取数据之类的目的
  3. P119把内置若干控件组合的linearlayout作为一个独立的继承类,通过某种形式动态构成,在别的activity里引用以实现共用带有返回和home按键的title(按键响应函数也共用)
  4. P125制作带有图片的listview控件(linearlayout+imageview+textview)

常用控件

API版本问题:源码的编译环境版本不对导致编译错误

想到一个点子,直接用新建工程文件里的各种版本号替换也可以,但步骤1和3还是不能省。
1、在grade app中的default添加如下代码:

    allprojects {
        repositories {
            jcenter()
            maven{
                url "https://maven.google.com"
            }
        }
    }

2、手动查看编译环境sdk tool 和 sdk buld tool版本,修改出错grade app中各个版本,参照https://blog.csdn.net/mhl18820672087/article/details/78385361/
3、根据警告内容的提示,很可能让你把compile字样需全部换成 → implementation,(因为API改变了,有些老程序没更新,沿用原来的写法)照做即可。

亲自尝试后发现:123都有各自一定的特点,少改一个都不行。

android {
    compileSdkVersion 26				//A 				A B C 必须一致,修改时有提示他们3个不能低于其中某一个,用的平台版本,多尝试吧
    buildToolsVersion "29.0.0"		//和自己软件的 Android SDK → SDK tools→android sdk tool一致29,他和update信息里的26还不一样。
    defaultConfig {
        applicationId "com.example.broadcasttest2"
        minSdkVersion 15			//不用管
        targetSdkVersion 26		//B
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    
    allprojects {
        repositories {
            jcenter()
            maven{
                url "https://maven.google.com"
            }
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:26.0.0'	//C
}

【EditText 】

【XML】

          //没有输入时显示的文本

【Acitvity】

		String str = edText1.getText().toString();

【Button】

方法一:
【XML】

【Activity】

 public class MyActivity extends Activity {
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.content_layout_id);

		 //这里开始 调用按键,设置按键的click事件的监听器
         final Button button = findViewById(R.id.button_id);
         button.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 // Code here executes on main thread after user presses button
             }
         });
     }
 }

方法二:
【XML】

【Activity】

/** Called when the user clicks the Send button */
public void sendMessage(View view) {
    // Do something in response to button
}

方法三:
【Activity】

		Button button_ToTable = (Button) getView().findViewById(R.id.button_ToTable);
		button_ToTable.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				//do something
			}
		});

【Toast】

//就一句话,直接用,第3个参数是显示的时间

Toast.makeText(this, "我是Toast", Toast.LENGTH_SHORT).show();

【ImageView】

使用方法:复制文件到\app_intent\app\src\main\res\drawable应该就会自动出现了,若没出现res→new→文件→添加
【XML】

    

【Activity】

                ImageView vv = (ImageView)findViewById(R.id.imageView_1);
                vv.setImageResource(R.drawable.img_2);

【menu】

res→NEW→androin resource director→选择menu以创建menu的文件夹(xml所在目录)
res→MENU→NEW→MENU resource file→menu控件及其xml文件添加成功
【XML】
需要手动添加item


    
    

【Activity】
Ctrl + O 搜索重写onCreateOptionsMenu构建方法,或者直接复制,onCreateOptionsMenu返回true后菜单显示,实测下面方法中仅onPrepareOptionsMenu和选择item有效。

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        /** 此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例。 返回true则显示该menu,false 则不显示; (只会在第一次初始化菜单时调用) Inflate the menu; this adds items to the 
action bar*/
        getMenuInflater().inflate(R.menu.main, menu);
        Toast.makeText(this, "onCreateOptionsMenu", Toast.LENGTH_SHORT).show();
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        /**在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用。 同样的,返回true则显示该menu,false 则不显示; (可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等) TODO Auto-generated method stub */
        //Toast.makeText(this, "onPrepareOptionsMenu", Toast.LENGTH_SHORT).show();
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public void onOptionsMenuClosed(Menu menu) {
        /**每次菜单被关闭时调用. (菜单被关闭有三种情形,menu按钮被再次点击、back按钮被点击或者用户选择了某一个菜单项) TODO  */
        Toast.makeText(this, "onOptionsMenuClosed", Toast.LENGTH_SHORT).show();
        super.onOptionsMenuClosed(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item_add:
                Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();
                break;
            case R.id.item_remove:
                Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show

();
                break;
            default:
        }
        return true;
    }

【intent】

使用方法:声明一个intent(main_activity.class,second_activity.class),调用startActivity(intent)或者startActivityForResult(intent,1)
【Activity】
方法一:不需要反馈结果的跳转

		//1、第一个activity触发跳转
                Intent intent = new Intent(MainActivity.this, 

_second_Activity.class);
                intent.putExtra("my_extral_data","Hello,second_activity");	//选用,相当于一个全局变量
                startActivity(intent);

		//2、第二个接到跳转后获取跳转的额外信息
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity__second_);

        Intent  intent_2nd = getIntent();
        String  data_2nd = intent_2nd.getStringExtra("my_extral_data");
        Log.d("2nd_act", "接受到act1的intent,内容为 "+data_2nd);

方法二:需要返回结果的跳转

		//1、第一个activity触发跳转
                Intent intent = new Intent(MainActivity.this, 

_second_Activity.class);
                intent.putExtra("my_extral_data","Hello,second_activity");
                startActivityForResult(intent,1);

		//2、在按键或某个事件中设置一个intent和返回值,结束当前的activity,

这里是按键2触发返回
        final Button button = findViewById(R.id.button_2);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
			//开始
                Intent  intent = new Intent();
                intent.putExtra("data_return","Hello you too ! class_1 !");
                setResult(RESULT_OK,intent);
                finish();
            }
        });

		//3、在第一个activity通过onActivityResult方法获得跳转回来的数据,根

据请求码requestCode, 
			获取对应请求码对应的结果码resultCode(通常为OK或取消)、和

Extra数据

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returnedData = data.getStringExtra("data_return");
                    Toast.makeText(this, "OK", Toast.LENGTH_SHORT).show();
                    Log.d("FirstActivity", "来自2nd_activity intent返回的值

为"+returnedData);
                }
                break;
            default:
        }
    }
		//4、当必须一个返回值,防止用户通过“返回键”结束2nd_activity,需要

重写返回键
    @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra( "data_return", "Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }

【ProgressDialog】

Android Studio开发实用notebook_第1张图片
【Activity】
使用方法:把以下代码添加到事件中

        ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setTitle("This is ProgressDialog");
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(true);
        progressDialog.show();

【AlertDialog】

Android Studio开发实用notebook_第2张图片

【Spiner】下拉选择框

1、XML布局文件拉出控件并给id
2、class区域声明spiner控件、adaper并初始化一个string数组
3、oncreat中ini连接变量名和控件,连接adapter到spiner,连接完成选择后触发的方法,收工。
参考:https://blog.csdn.net/gongzibai/article/details/7970930

【Activity】使用方法:把以下代码添加到事件中

        AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
        dialog.setTitle("警告框");
        dialog.setMessage("内容");
        dialog.setCancelable(false);
        dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "OK", Toast.LENGTH_SHORT).show();
            }
        });
        dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "CANCEL", Toast.LENGTH_SHORT).show();
            }
        });

        dialog.show();

【ListView】

方法一:通过ArrayAdapter把ListView和字符串数组连接起来

        //activity内
        String[] fruit ={"apple","banana","orange","watemelon","pear","grape","pinapple","strawberry","cherry","mango","apple","banana","orange","watemelon","pear","grape","pinapple","strawberry","cherry","mango"};
        ListView listView = (ListView)findViewById(R.id.listView_1);
        //ArrayAdapter第二个参数为listview的显示样式,单个字符串单行显示
        ArrayAdapter adaper_1 = new ArrayAdapter(this,android.R.layout.simple_list_item_1 ,fruit);
        listView.setAdapter(adaper_1);

        //为列表视图中选中的项添加响应事件,不明觉厉
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                String result = parent.getItemAtPosition(position).toString();//获取选择项的值
                Toast.makeText(MainActivity.this,"您点击了"+result,Toast.LENGTH_SHORT).show();
            }
        });

方法二:直接在ListView构造文件里添加绑定关系
1、ListView的XML文件里添加与字符串阵列list的绑定关系

        

2、在res的String.xml里添加符串阵列list


       
        第一行
        第二行
        第三行
        第四行
        第五行
        第六行
        第七行
        第八行
        第九行
        第十行
        第十一行
        第十二行
        第十三行
    

3、完成1、2就已经成功绑定,点击事件绑定同方法一
activity内

       ListView listView = (ListView)findViewById(R.id.listView_1);

        //为列表视图中选中的项添加响应事件,不明觉厉
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                String result = parent.getItemAtPosition(position).toString();//获取选择项的值
                Toast.makeText(MainActivity.this,"您点击了"+result,Toast.LENGTH_SHORT).show();
            }
        });

【读写文件操作】

《第一行代码中》
FileOutputStream out = null;
BufferedWriter writer = null;
out = openFileOutput(“data”,Context.MODE_PRIVATE);
会出错:Unhandled exception: java.io.FileNotFoundException
在网上找到相关源码作对比发现openFileOutput必须有try{} catch(){}并且catch()内还必须有对象,如(IOException e、FileNotFoundException e),还有import的文件有几个不能少,且不能通过快捷键自动导入,必须手动。

【写入文件】在com.xxx.program_name下data/data/files目录下,不存在会自动创建

/*import 需手动加入到文件头*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;


    private void WriteFile() {
        try {
            FileOutputStream outStream = this.openFileOutput("fileName.txt",MODE_PRIVATE);
            try {
                // 写出文件
                outStream.write(my_data.getBytes());
                outStream.flush();
                outStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

【读取文件】返回一个字符串

   private String ReadFile() {
        FileInputStream inputStream;
        byte[] buffer = null;
        try {
            inputStream = this.openFileInput("data.txt");
            try {
                // 获取文件内容长度
                int fileLen = inputStream.available();
                // 读取内容到buffer
                buffer = new byte[fileLen];
                inputStream.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 返回文本信息
        if (buffer != null)
            return EncodingUtils.getString(buffer, "utf-8");
        else
            return "";
    }

【SharedPreference】共享参数,可以代替全局变量,存在/data/data/com.xxx.package/shared_prefs/data.xml文件里,调用比较方便

package com.example.sharedpreferencestest;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveData = (Button) findViewById(R.id.save_data);
        saveData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                editor.putString("name", "Tom");
                editor.putInt("age", 28);
                editor.putBoolean("married", false);
                editor.apply();
            }
        });
        Button restoreData = (Button) findViewById(R.id.restore_data);
        restoreData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
                String name = pref.getString("name", "");
                int age = pref.getInt("age", 0);
            }
        });
    }
}

【SQLite 增删改查】

XML构造文件就几个按键




    

mainactivity

package com.example.databasetest;

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.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
        //  【增】new一个ContentValues 类数据→装载→db.insert("Book", null, values);第二个参数:缺省时赋值为null
        Button addData = (Button) findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                // 开始组装第一条数据
                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages", 454);
                values.put("price", 16.96);
                db.insert("Book", null, values); // 插入第一条数据
                values.clear();
                // 开始组装第二条数据
                values.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages", 510);
                values.put("price", 19.95);
                db.insert("Book", null, values); // 插入第二条数据
            }
        });
        //  【删】db.delete删除页数属性大于500的数据,注意:页码属性为integer,而输入参数都是字符串
        Button deleteButton = (Button) findViewById(R.id.delete_data);
        deleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[] { "500" });
            }
        });
        //  【改】 把名字为达芬奇密码的书价格更新为10.99元
        Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
            }
        });
        //  【查】cursor = db.query 返回一个指针,通过指针从表头查到表尾,通过log展示所有属性
        Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                // 查询Book表中所有的数据
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        // 遍历Cursor对象,取出数据并打印
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndex("price"));
                        Log.d("MainActivity", "book name is " + name);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book pages is " + pages);
                        Log.d("MainActivity", "book price is " + price);
                    } while (cursor.moveToNext());
                }
                cursor.close();
            }
        });
    }

}

package包中引用的java文件:重构一个类SQLiteHelper类:MyDatabaseHelper extends SQLiteOpenHelper

package com.example.databasetest;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyDatabaseHelper extends SQLiteOpenHelper {

    public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)";

    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code integer)";

    private Context mContext;

    public MyDatabaseHelper(Context context, String name,
                            SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }

}

线程

首先讲一下进程和线程的区别:

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。

线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。

线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。

多进程是指操作系统能同时运行多个任务(程序)。

多线程是指在同一程序中有多个顺序流在执行。

在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。

一、扩展java.lang.Thread类

public class Main {

    public static void main(String[] args) {
        MyThread T1 = new MyThread("A");
        MyThread T2 = new MyThread("B");
        T1.start();
        T2.start();


    }

}

 class MyThread extends Thread {
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name+":"+i);
            try {
                sleep(1000); //休眠1秒,避免太快导致看不到同时执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
}

输出:

A:0
B:0
A:1
B:1
B:2
A:2
B:3
A:3
A:4
B:4

程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用MitiSay的两个对象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。

注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
从程序运行的结果可以发现,多线程程序是乱序执行。因此,只有乱序执行的代码才有必要设计为多线程。
Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。(要看效果要去除sleep方法,然后加大打印次数)

二、实现java.lang.Runnable接口

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
复制代码

public class Main {

    public static void main(String[] args) {

        //测试Runnable
        MyThread1 t1 = new MyThread1();
        new Thread(t1).start();//同一个t1,如果在Thread中就不行,会报错
        new Thread(t1).start();
        new Thread(t1).start();

    }

}
class MyThread1 implements Runnable{
    private int ticket = 10;
    @Override
    //记得要资源公共,要在run方法之前加上synchronized关键字,要不然会出现抢资源的情况
    public synchronized  void  run() {
        for (int i = 0; i <10; i++) {
            if (this.ticket>0) {
                System.out.println("卖票:ticket"+this.ticket--);
            }
        }
        
    }
    
}

输出:

卖票:ticket10
卖票:ticket9
卖票:ticket8
卖票:ticket7
卖票:ticket6
卖票:ticket5
卖票:ticket4
卖票:ticket3
卖票:ticket2
卖票:ticket1

这里要注意每个线程都是用同一个实例化对象,如果不是同一个,效果就和上面的一样了!

总结:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

你可能感兴趣的:(Android Studio开发实用notebook)