java版Android前端+SpringBoot后端开发学习


看的书叫:第一行代码 第二版 ,在微信读书(APP)上可以免费看
用的是:Android Studio
因为做毕设是安卓的,所以在学,学到够做一个毕设就不写了。

遇到的问题

1.Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
jdk要用11。8不可以哦。
在这里插入图片描述解决:
File > Settings > 搜索 Gradle > 选择我们需要的版本 > Apply > ok
在这里插入图片描述
2.Gradle sync failed: Cause: startup failed:
网太差,更新gradle的地址很慢或者写错了,使得他每次加载项目的时候没办法更新gradle
在这里插入图片描述
下载地址:
distributionUrl=https://downloads.gradle-dn.com/distributions/gradle-7.0.3-bin.zip
解决:到这个地址下载好,然后本地运行已经下载好的就行。
在这里插入图片描述
或者找个网好的地方新建项目。。。

1.Android端学习笔记

一、 log日志工具

(log是很好用的调试工具!)
TAG:“一般是类名,或者是自定义的过滤器tag”
Log.d(TAG, “信息”);
在logcat里搜信息,就能找到log记录
在这里插入图片描述这这里可以自定义过滤器
在这里插入图片描述

快捷方式:
debug:logd+tab:Log.d();
除了debug还有verbose、info、warn、error
logt+tab可以快捷创建tag的局部变量
private static final String TAG = “类名”;

二、Activity活动

活动的基本用法

创建按钮

1.新建按钮页面文件

<?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.在活动中加载布局

setContentView(R.layout.first_layout);//加载页面

在这里插入图片描述3.在AndroidManifest文件中注册活动

<?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>

在这里插入图片描述

创建Toast-按下按钮弹出Toast

1.按钮实例化
2.注册监听器

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();
            }
        });
    }
}

创建菜单-使用菜单menu

在这里插入图片描述
1.先在 XML 中定义一个菜单。新建menu文件夹,新建main.xml;
在这里插入图片描述
在main.xml文件中建立选项按键。

<?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.让菜单显示出来,在Activity中重写onCreateOptionsMenu()方法。
重写快捷键ctrl+o

  • MenuInflater :用来解析定义在menu 目录下的菜单布局文件的
  • Inflate():就是将xml定义的一个布局找出来
 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
    
        MenuInflater inflater = getMenuInflater();//MenuInflater 用来解析定义在menu目录下的菜单布局文件的
        inflater.inflate(R.menu.main, menu);//Inflate()作用就是将xml定义的一个布局找出来
        return true;
    }

通过getMenuInflater()方法获取获取MenuInflater对象,在调用inflate方法就可以为活动创建当前对象了。

inflater()方法接受两个参数,第一个是我们通过制定哪一个资源文件来创建菜单,这里传入R.menu.main;第二个用于指定我们的菜单项将添加到那一个Menu对象中,这里直接使用onCreateOptionsMenu()方法中的menu对象。

最后返回true 显示出来,如果返回false则不显示。

3.定义菜单响应事件
重写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;
    }

销毁一个活动

按下手机上的back即可
自由用代码的方式:修改按钮监听器里的代码如下:

button_1.setOnClickListener(new View.OnClickListener(){
    
    
      @Override
      public void onClick(View view) {
    
    
          finish();
      }
});

使用Intent在活动穿梭

点击应用图标后只能进入主活动,如何从主活动跳转到其他活动呢?
intent 英:目的 意图

使用显式Intent进行跳转

Intent(上下文,想要启动的目标活动)
在上下文下打开想要启动的目标活动
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);
在MainActivity这个上下文下打开SecondActivity这个活动

使用隐式Intent进行跳转

在Manifest.xml配置文件中配置intent-filter过滤器节点,给目标活动配置(跳转目标)

 <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>

就像暗号,俩都是a,所以匹配上了
给触发按钮设置监听

        button_1.setOnClickListener(new View.OnClickListener(){
    
    
            @Override
            public void onClick(View view) {
    
    
                Intent intent = new Intent("a");//想启动能相应那串字的活动
                startActivity(intent);//启动目标这个对象
            }
        });

只有当action、category都匹配上,才能成功。

刚才只有一个action,能成功是因为category用的是默认的,接下来也同样配置一下category。

 <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);//启动目标这个对象
            }
});

更多隐式Intent用法

展示一个网页
 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);//启动目标这个对象
            }
        });

intent的action是Intent.ACTION_VIEW,这是一个系统内置的动作。
setData()用于指定intent正在操作的数据,接收的是url。

调用系统拨号
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);//启动目标这个对象
            }
        });

使用Intent传递数据

传递数据给下一个活动

使用intent.putExtra(键,值)存放字符串,extra 英:附加物
使用intent.getStringExtra(键)获取字符串

(MainActivity)现在把字符串hello从FirstActivity传递到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)接收字符串:

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);
    }   
}
返回数据给上一个活动

在ActivityA中用startActivityForResult()方法启动了Activity B,并且在B中通过setResult()方法给A返回数据,A使用onActivityResult回调函数接收数据。
1.在ActivityA中用startActivityForResult()方法启动了Activity B
(MainActivity)

button_1.setOnClickListener(new View.OnClickListener(){
    
    
            @Override
            public void onClick(View view) {
    
    
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivityForResult(intent,1);//启动目标这个对象
            }
        });

在启动另外一个Activity的时候,有两种方法: 一种就是直接使用startActivity, 另一种是使用startActivityForResult。 startActivityForResult的主要作用就是它可以回传数据。

startActivityForResult(Intent intent, int requestCode);

  • 第一个参数:一个Intent对象,用于携带将跳转至下一个界面中使用的数据,使用putExtra(A,B)方法,此处存储的数据类型特别多,基本类型全部支持。

  • 第二个参数:请求码,为了区分启动不同的Intent,或者传递不同的数据使用,作为一种不同启动的标识。如果> =0,当Activity结束时requestCode将归还在onActivityResult()中。以便确定返回的数据是从哪个Activity中返回。

2.在B中通过setResult()方法给A返回数据

(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)

  • 第一个参数:RESULT_OK 用于向上一个活动返回处理结果。
  • 第二个参数:intent,用于携带数据。

3.A页面接收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)

  • 第一个参数:requestCode 请求码 (哪个活动发出请求的标识)。
  • 第二个参数:resultCode 处理结果(RESULT_OK)。
  • 第三个参数:data 返回的intent数据。

在这里插入图片描述
成功返回数据

如果用户通过手机的back键返回到A页面,可以重写onBackPressed():
(SecondActivity)

 @Override
    public void onBackPressed() {
    
    
        Intent intent = new Intent();//只是传递数据而已
        intent.putExtra("return_data","hello 你按了back");//把传递的数据放进去
        setResult(RESULT_OK,intent);//向上一个活动返回数据
        finish();//销毁当前活动
    }

活动的生命周期

活动的生存期

Activity类定义了7个回调方法。

(1)onCreate():在活动第一次被创建的时候调用。在这个方法中完成活动的初始化操作,例如加载布局、绑定事件等

(2)onStart():在活动由不可见变成可见的时候调用。

(3)onResume():在活动准备好和用户进行交互的时候调用。此时活动位于返回栈的栈顶,并且处于运行状态。

(4)onPause():在系统准备去启动或者恢复另一个活动的时候调用。在该方法中将一些销毁CPU的资源释放掉,保存关键数据。该方法执行速度一定要快,不然会影响栈顶活动的使用

(5)onStop():在方法完全不可见的时候调用。注意onStop()与onPause()的区别。

(6)onDestroy():在活动被销毁之前调用。

(7)onRestart():在活动由停止状态变为运行状态前调用。
该图片出自https://blog.csdn.net/u013476556/article/details/44976947该图片出自https://blog.csdn.net/u013476556/article/details/44976947

内存不足,数据恢复

内存不足可能回收stop时的活动,临时数据会丢失,用户会生气。
解决:
onSaveInstanceState()回调函数,保证回收之前一定被调用。

 @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
    
    
        super.onSaveInstanceState(outState);
        outState.putString("data_key","临时数据");
    }

这样就保存在Bundle对象里。
怎么恢复?每次onCreate()里面有Bundle参数,平时是null,如果回收前用onSaveInstanceState保存过的话,这个参数就会带之前保存过的数据,修改onCreate取出来即可。

 @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也可以用来传数据,先把数据存在Bundle,再存到intent。

活动的启动模式

修改活动的启动模式在AndroidManifest.xml中,launchMode = “模式”

 <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

默认模式,每启动一个活动,那个活动就会入栈,他也不在乎这个活动是否在栈里已存在,每次启动活动就会创建一个新的实例。

singleTop

栈顶单例,在启动活动时,发现返回栈的栈顶是这个活动,不会创建新的实例。如果栈顶不是这个活动,还是会创建新的实例的。

singleTask

启动活动时,检查有没有活动实例,如果有就直接用这个实例,然后把此活动之上的所有活动都出栈,没有的话就创建新的实例。

singleInstance

启用一个单独的新栈管理这个活动,解决共享活动实例问题。
销毁活动也是先销毁主栈,再清新栈。

技巧

知道当前活动是哪个

在当前活动的onCreate中写:

Log.d("MainActivity", getClass().getSimpleName());

可以在日志中看见。

随时随地退出程序

如果启动栈里有很多活动,现在想直接退出程序,按home也没用(只是挂起),可以新建ActivityCollector类作为活动管理器:

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());//杀死当前进程
    }
}

每个活动onCreate就addActivity(this),onDestory就removeActivity(this)。
想退出活动就调用finish。

启动活动最佳写法

MainActivity想启动SecondActivity,但不知道传值的键是什么,解决方法:
(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");
            }
        });

三、UI

最后再详细写吧,想用什么查一下就好了。

控件

红色为常用控件
在这里插入图片描述图片来源:https://blog.csdn.net/wufen12334/article/details/53072538

TextView

显示文本信息

Button

按钮

EditText

输入和编译内容

ImageView

展示图片

ProgressBar

显示一个进度条,表示程序正在加载一些数据。

AlertDialog

在当前页面弹出一个对话框,这个对话框置顶于所有界面元素之上,能屏蔽掉其他控件的交互能力,可以警告,提示等。

ProgressDialog

在界面上弹出一个对话框,能屏蔽掉其他控件的交互能力,显示一个进度条,表示当前操作比较耗时,请等待。

自定义控件

基本布局

LinearLayout线性布局

RelativeLayout相对布局

FrameLayout帧布局

所有控件默认放在左上角

百分比布局

任意比例分割布局

开源UI框架

Side-Menu.Android 分类侧滑菜单

https://github.com/Yalantis/Side-Menu.Android
在这里插入图片描述

AndroidSwipeLayout 滑动Layout

滑动Layout,支持单个View,ListView,GridView。
项目地址:
https://github.com/daimajia/AndroidSwipeLayout
在这里插入图片描述

安卓端功能实践

1.在fragment中显示列表信息

跟着这个文章学的

问题:写repository时,用okhttp从后台调来参数然后封装成bean后return时,先return再调线程的,所以永远为空。
解决办法::
Thread:主线程等待子线程执行完毕再执行解决办法

2.同一按钮在1秒内只会响应一次点击事件

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) {
    
    
                // 进行点击事件后的逻辑操作
            }
        });

ScrollView中嵌套ListView

ScrollView中嵌套ListView

fragment之间跳转

跟着这个学的
还有这个

计时器

计时器

倒计时跳转

倒计时实现两种方式

踩过的坑

顶部出现空白

顶部出现空白

未完待续…

2.服务端

用的idea,springboot
1.搭建springboot项目,看的这个文章就够用了.
像这样就搭起来了哟,接下来就可以写服务器端的接口辣
在这里插入图片描述
2.接下来搭建dao,service等,完成登录功能
看的是这个文章,从建立UserBean文件那跟着写的
注意这篇文章中有点错误,按照下面这个改就可以。

测试类中Demo1ApplicationTests中原始代码是@RunWith(SpringRunner.class)报错,使用@MapperScan(“com.example.test.mapper”)替代; application.properties中spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver,添加cj; UserServiceImpl类中private UserMapper userMapper,原始代码是@Autowired,报错后使用 @Resource替代;UserMapper类使用@Repository ,getInfo该为UserBean getInfo(@Param(“name”) String name, @Param(“password”)String password); user表中添加好一条数据“1,a,a”

测试成功:
在这里插入图片描述
快捷键
alt+insert :创建get set
然后我想用前后端分离
vue+springboot

3.前后端通信

跟着这个视频学会的:安卓APP项目前后端通信连接 android studio与springboot为例 postman使用方法温习

3.1先学会最简单的,传string过去,返回string。

在build.gradle在这里插入图片描述

implementation 'com.squareup.okhttp3:okhttp:4.4.1'

链接到服务器:

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();

我犯的错
没报错,一直没反应,因为我忘记写start了。
报错了,因为我implementation了两版本的个okhttp3

SpringBoot服务这么写的:
在这里插入图片描述


@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 "服务器出错了";
        }
    }
}

其中@ResponseBody是return的值不是个xml页面,得必须加上
@RequestParam就是要传的参数
成功了:
在这里插入图片描述测后端接口用postman,免费的,不要钱,官网就能下。

mysql数据库中随机查询出5条数据进行测试的sql编写

SELECT * FROM employees ORDER BY RAND() LIMIT 5;

猜你喜欢

转载自blog.csdn.net/qq_30738155/article/details/122518974