想到一个点子,直接用新建工程文件里的各种版本号替换也可以,但步骤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
}
【XML】
//没有输入时显示的文本
【Acitvity】
String str = edText1.getText().toString();
方法一:
【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】
//直接声明click挂钩的响应函数
【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
}
});
//就一句话,直接用,第3个参数是显示的时间
Toast.makeText(this, "我是Toast", Toast.LENGTH_SHORT).show();
使用方法:复制文件到\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);
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(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 progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("This is ProgressDialog");
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(true);
progressDialog.show();
1、XML布局文件拉出控件并给id
2、class区域声明spiner控件、adaper并初始化一个string数组
3、oncreat中ini连接变量名和控件,连接adapter到spiner,连接完成选择后触发的方法,收工。
参考:https://blog.csdn.net/gongzibai/article/details/7970930
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();
方法一:通过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);
}
});
}
}
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):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立