Welcome to learn together!
- problems encountered
- 1. Android study notes
- 2. Server
- 3. Front-end and back-end communication
The book I’m reading is called: The First Line of Code, Second Edition, which can be
read : Android Studio
, because the completion design is Android, so I’m studying, and I don’t write after learning enough to do a complete design. up.
problems encountered
1. Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
jdk needs to use Java 11. 8 is not allowed.
Solution:
File > Settings > Search Gradle > Select the version we need > Apply > ok
2.Gradle sync failed: Cause: startup failed:
The network is too bad, the address of updating gradle is very slow or wrongly written, making him load the project every time There is no way to update the gradle
download address:
distributionUrl=https://downloads.gradle-dn.com/distributions/gradle-7.0.3-bin.zip
Solution: go to this address to download it, and then run it locally. .
Or find a place with a good network to create a new project. . .
1. Android study notes
1. log log tool
(log is a very useful debugging tool!)
TAG: "Usually a class name, or a custom filter tag"
Log.d(TAG, "information");
search for information in logcat, and you can find log records
Here you can customize the filter
Shortcut:
debug:logd+tab:Log.d();
In addition to debug, there are verbose, info, warn, error
logt+tab can quickly create a local variable of tag
private static final String TAG = "class name";
2. Activity
Basic Usage of Activities
create button
1. Create a new button page file
<?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="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button_1" />
</LinearLayout>
2. Load the layout in the activity
setContentView(R.layout.first_layout);//加载页面
3. Register the event in the AndroidManifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<activity
android:name=".MainActivity"
android:label="this is FirstActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Create Toast - Press the button to pop up Toast
1. Button instantiation
2. Register listener
public class MainActivity extends AppCompatActivity {
private static final String TAG = "data";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);//保存当前Activity的状态信息
setContentView(R.layout.first_layout);//加载页面
//按钮实例化
Button button_1 = (Button) findViewById(R.id.button_1);
Log.d(TAG, "onCreate execute");
//注册监听器
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"you clicked Button_1", Toast.LENGTH_SHORT).show();
}
});
}
}
create menu - use menu menu
1. First define a menu in XML. Create a new menu folder, create a new main.xml;
create an option button in the main.xml file.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
2. To display the menu, override the onCreateOptionsMenu() method in the Activity.
Rewrite the shortcut key ctrl+o
- MenuInflater: used to parse the menu layout files defined in the menu directory
- Inflate(): Find out a layout defined by xml
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();//MenuInflater 用来解析定义在menu目录下的菜单布局文件的
inflater.inflate(R.menu.main, menu);//Inflate()作用就是将xml定义的一个布局找出来
return true;
}
Obtain the MenuInflater object through the getMenuInflater() method, and create the current object for the activity by calling the inflate method.
The inflater() method accepts two parameters, the first is which resource file we create to create the menu, here we pass in R.menu.main; the second is used to specify which Menu object our menu items will be added to , here directly use the menu object in the onCreateOptionsMenu() method.
Finally return true to display, if return false it will not be displayed.
3. Define the menu response event
and rewrite onOptionsItemSelected
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.add_item:
Toast.makeText(this, "You click add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "You click Remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
destroy an event
Press back on the phone to
use the code freely: modify the code in the button listener as follows:
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
finish();
}
});
Use Intent to shuttle between activities
After clicking the application icon, you can only enter the main activity. How to jump from the main activity to other activities?
intent English: purpose intent
Use an explicit Intent to jump
Intent (context, the target activity you want to start)
Open the target activity you want to start under the context
Intent(Context packageContext, Class<?> cls)
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
Intent(MainActivity.this, SecondActivity.class);
Open the SecondActivity activity in the context of MainActivity
Jump using implicit Intent
Configure the intent-filter filter node in the Manifest.xml configuration file to configure the target activity (jump target)
<activity
android:name=".SecondActivity"
android:exported="false"
android:label="this is SecondActivity">
<intent-filter>
<action android:name="a" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Just like a secret code, both are a, so they match.
Set up a monitor for the trigger button
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent("a");//想启动能相应那串字的活动
startActivity(intent);//启动目标这个对象
}
});
Only when the action and category match, can it succeed.
There was only one action just now, and it succeeded because the default category was used. Next, configure the category as well.
<activity
android:name=".SecondActivity"
android:exported="false"
android:label="this is SecondActivity">
<intent-filter>
<action android:name="a" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="b" />
</intent-filter>
</activity>
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent("a");//想启动能相应那串字的活动
intent.addCategory("b");
startActivity(intent);//启动目标这个对象
}
});
More implicit Intent usage
display a web page
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW);//系统内置动作
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);//启动目标这个对象
}
});
The action of the intent is Intent.ACTION_VIEW, which is a built-in action of the system.
setData() is used to specify the data that the intent is operating on, and the url is received.
call system dial
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL);//想启动能相应那串字的活动
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);//启动目标这个对象
}
});
Pass data using Intent
Pass data to next activity
Use intent.putExtra (key, value) to store strings, extra English: extras
Use intent.getStringExtra (key) to get strings
(MainActivity) now passes the string hello from FirstActivity to SecondActivity:
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("extra_data","hello");
startActivity(intent);//启动目标这个对象
}
});
(SecondActivity) Receive String:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();//获取用于启动SecondActivity数据更新后的Intent
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
}
Return data to the previous activity
Start Activity B with the startActivityForResult() method in ActivityA, and return data to A through the setResult() method in B, and A uses the onActivityResult callback function to receive the data.
1. Start Activity B
(MainActivity) with the startActivityForResult() method in ActivityA
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,1);//启动目标这个对象
}
});
When starting another Activity, there are two methods: one is to use startActivity directly, and the other is to use startActivityForResult. The main function of startActivityForResult is that it can return data.
startActivityForResult(Intent intent, int requestCode);
-
The first parameter: an Intent object, which is used to carry the data that will be used in the next interface. Use the putExtra(A,B) method. There are many data types stored here, and all basic types are supported.
-
The second parameter: the request code, in order to distinguish between starting different Intents, or to pass different data, it is used as a different starting identifier. If >=0, requestCode will be returned in onActivityResult() when the Activity ends. In order to determine which Activity the returned data is returned from.
2. In B, return data to A through the setResult() method
(SecondActivity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button_2 = (Button) findViewById(R.id.button_2);
button_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();//只是传递数据而已
intent.putExtra("return_data","hello");//把传递的数据放进去
setResult(RESULT_OK,intent);//向上一个活动返回数据
finish();//销毁当前活动
}
});
}
setResult(RESULT_OK,intent)
- The first parameter: RESULT_OK is used to return the processing result to the previous activity.
- The second parameter: intent, used to carry data.
3. A page receives the data returned by B
(MainActivity)
@SuppressLint("MissingSuperCall")
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnData = data.getStringExtra("return_data");
Log.d("MainActivity", returnData);
}
break;
default:
}
}
onActivityResult(int requestCode, int resultCode, Intent data)
- The first parameter: requestCode request code (identification of which activity made the request).
- The second parameter: resultCode processing result (RESULT_OK).
- The third parameter: the intent data returned by data.
Return data successfully
If the user returns to page A through the back button of the mobile phone, onBackPressed() can be rewritten:
(SecondActivity)
@Override
public void onBackPressed() {
Intent intent = new Intent();//只是传递数据而已
intent.putExtra("return_data","hello 你按了back");//把传递的数据放进去
setResult(RESULT_OK,intent);//向上一个活动返回数据
finish();//销毁当前活动
}
activity life cycle
activity lifetime
The Activity class defines 7 callback methods.
(1) onCreate(): Called when the activity is first created. In this method, complete the initialization of the activity, such as loading the layout, binding events, etc.
(2) onStart(): Called when the activity changes from invisible to visible.
(3) onResume(): Called when the activity is ready to interact with the user. At this point the activity is at the top of the return stack and is in the running state.
(4) onPause(): Called when the system is ready to start or resume another activity. In this method, some resources that destroy the CPU are released to save key data. The execution speed of this method must be fast, otherwise it will affect the use of stack top activities
(5) onStop(): Called when the method is completely invisible. Note the difference between onStop() and onPause().
(6) onDestroy(): Called before the activity is destroyed.
(7) onRestart(): Called before the activity changes from the stopped state to the running state.
The picture is from https://blog.csdn.net/u013476556/article/details/44976947
Insufficient memory, data recovery
Insufficient memory may recycle stopped activities, temporary data will be lost, and users will be angry.
Solution:
The onSaveInstanceState() callback function is guaranteed to be called before recycling.
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data_key","临时数据");
}
This is stored in the Bundle object.
How to recover? Every time there is a Bundle parameter in onCreate(), which is usually null. If it is saved with onSaveInstanceState before recycling, this parameter will bring the previously saved data, and you can modify onCreate to get it out.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
if(savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
Log.d("SecondActivity", "tempData");
}
}
Bundle can also be used to transfer data, first store the data in the Bundle, and then save it in the intent.
Activity launch mode
Modify the launch mode of the activity In AndroidManifest.xml, launchMode="mode"
<activity
android:name=".ThirdActivity"
android:launchMode="standard"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" />
</intent-filter>
</activity>
standard
In the default mode, every time an activity is started, that activity will be pushed onto the stack, and he doesn't care whether the activity already exists in the stack, and a new instance will be created every time the activity is started.
singleTop
The singleton at the top of the stack, when the activity is started, it is found that the top of the return stack is this activity, and no new instance will be created. If the top of the stack is not the activity, a new instance will still be created.
singleTask
When starting an activity, check whether there is an activity instance, if there is, use this instance directly, and then pop all the activities above this activity out of the stack, if not, create a new instance.
singleInstance
Enable a separate new stack to manage this activity, solving the shared activity instance problem.
The destruction activity also destroys the main stack first, and then refreshes the stack.
Skill
Know which is currently active
In the onCreate of the current activity write:
Log.d("MainActivity", getClass().getSimpleName());
can be seen in the logs.
Exit the program anytime, anywhere
If there are many activities in the startup stack, and now you want to exit the program directly, pressing home is useless (just hangs), you can create a new ActivityCollector class as the activity manager:
package com.example.myapplication;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for (Activity activity:activities) {
if(! activity.isFinishing()){
activity.finish();
}
}
android.os.Process.killProcess(android.os.Process.myPid());//杀死当前进程
}
}
Each activity onCreate addsActivity (this), and onDestory removeActivity (this).
Call finish when you want to exit the activity.
Best way to start a campaign
MainActivity wants to start SecondActivity, but it doesn't know what the key of the value is, the solution:
(SecondActivity)
//封装参数启动当前活动
public static void actionStart(Context context,String data1,String data2){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("data1",data1);
intent.putExtra("data2",data2);
context.startActivity(intent);
}
(MainActivity)
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
SecondActivity.actionStart(MainActivity.this,"data1","data2");
}
});
3. UI
Write it in detail at the end, just check what you want to use.
control
Red is
the image source of commonly used controls: https://blog.csdn.net/wufen12334/article/details/53072538
TextView
display text information
Button
button
EditText
Input and compile content
ImageView
Show pictures
ProgressBar
A progress bar is displayed, indicating that the program is loading some data.
AlertDialog
A dialog box pops up on the current page. This dialog box is placed on top of all interface elements, which can block the interaction ability of other controls, and can warn, prompt, etc.
ProgressDialog
A dialog box pops up on the interface, which can block the interaction ability of other controls, and display a progress bar, indicating that the current operation is time-consuming, please wait.
custom control
basic layout
LinearLayout linear layout
RelativeLayout relative layout
FrameLayout frame layout
All controls are placed in the upper left corner by default
percentage layout
Arbitrary ratio split layout
Open source UI framework
Side-Menu.Android classification side menu
https://github.com/Yalantis/Side-Menu.Android
AndroidSwipeLayout sliding Layout
Sliding Layout supports single View, ListView, GridView.
Project address:
https://github.com/daimajia/AndroidSwipeLayout
Android function practice
1. Display list information in fragment
Question: When writing a repository, use okhttp to transfer parameters from the background and then encapsulate them into beans and then return, return first and then adjust the thread, so it will always be empty.
Solution::
Thread: The main thread waits for the child thread to finish executing before executing the solution
2. The same button will only respond to one click event within 1 second
public abstract class OnMultiClickListener implements View.OnClickListener{
// 两次点击按钮之间的点击间隔不能少于1000毫秒
private static final int MIN_CLICK_DELAY_TIME = 1000;
private static long lastClickTime;
public abstract void onMultiClick(View v);
@Override
public void onClick(View v) {
long curClickTime = System.currentTimeMillis();
if((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
// 超过点击间隔后再将lastClickTime重置为当前点击时间
lastClickTime = curClickTime;
onMultiClick(v);
}
}
}
btn.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
// 进行点击事件后的逻辑操作
}
});
Nested ListView in ScrollView
Jump between fragments
timer
countdown jump
Countdown is implemented in two ways
stepped on pit
white space at the top
To be continued...
2. Server
The idea used, springboot
1. To build a springboot project, this article is enough .
It is set up like this, and then you can write the interface on the server side.
2. Next, build dao, service, etc. to complete the login function
What I read is this article, which was written following the establishment of the UserBean file.
Note that there are some mistakes in this article, just change it according to the following.
The original code in Demo1ApplicationTests in the test class is @RunWith(SpringRunner.class) reporting an error, use @MapperScan("com.example.test.mapper") instead; spring.datasource.driver-class-name=com.mysql in application.properties .cj.jdbc.Driver, add cj; private UserMapper userMapper in the UserServiceImpl class, the original code is @Autowired, use @Resource instead after reporting an error; UserMapper class uses @Repository, getInfo should be UserBean getInfo(@Param(“name”) String name, @Param("password")String password); A piece of data "1,a,a" has been added to the user table
The test is successful:
shortcut key
alt+insert: create a get set
and then I want to separate
vue+springboot with the front and back ends
3. Front-end and back-end communication
Follow this video to learn: Android APP project front-end communication connection android studio and springboot as an example Postman usage method review
3.1 Learn the simplest one first, pass the string in the past, and return the string.
In build.gradle add
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
Link to server:
new Thread(new Runnable() {
@Override
public void run() {
try {
//创建http客户端
OkHttpClient client = new OkHttpClient();
//创建表单体(参数)
FormBody.Builder params = new FormBody.Builder();
params.add("id", "1806050107");
params.add("password", "123456");
//创建http请求
Request request = new Request.Builder()
.url("http://192.168.43.73:8080/PartyMemberLoginIn")
.post(params.build())
.build();
//执行发送的指令
Response response = client.newCall(request).execute();
//回应
String responseData = response.body().string();
System.out.println(responseData);
userName.postValue(responseData);
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
The mistake I made :
No error was reported, and there was no response because I forgot to write start.
An error was reported, because I implemented two versions of okhttp3
The SpringBoot service is written like this:
@Controller
public class LoginInController {
//将Service注入Web层
@Autowired
private UserService userService;
@ResponseBody
@RequestMapping(value = "/PartyMemberLoginIn",method = RequestMethod.POST)
public String PartyMemberLoginIn(@RequestParam String id,@RequestParam String password){
try {
UserBean userBean = userService.PartyMemberLoginIn(id,password);
if(userBean!=null){
return "success";
}else{
return "登录失败";
}
}catch (Exception e){
return "服务器出错了";
}
}
}
Among them, @ResponseBody is the value of return, not an xml page, you must add
@RequestParam, which is the parameter to be passed
Success:
use postman to test the back-end interface, free, no money, you can download it from the official website.
Randomly query 5 pieces of data in the mysql database for testing sql writing
SELECT * FROM employees ORDER BY RAND() LIMIT 5;