欢迎一起学 耶耶!
遇到的问题1.Android端学习笔记一、 log日志工具二、Activity活动活动的基本用法创建按钮创建Toast-按下按钮弹出Toast创建菜单-使用菜单menu销毁一个活动 使用Intent在活动穿梭使用显式Intent进行跳转使用隐式Intent进行跳转更多隐式Intent用法展示一个网页调用系统拨号 使用Intent传递数据传递数据给下一个活动返回数据给上一个活动 活动的生命周期活动的生存期内存不足,数据恢复 活动的启动模式standardsingleTopsingleTasksingleInstance 技巧知道当前活动是哪个随时随地退出程序启动活动最佳写法 三、UI控件TextViewButtonEditTextImageViewProgressBarAlertDialogProgressDialog自定义控件 基本布局LinearLayout线性布局RelativeLayout相对布局FrameLayout帧布局百分比布局 开源UI框架Side-Menu.Android 分类侧滑菜单AndroidSwipeLayout 滑动Layout 安卓端功能实践1.在fragment中显示列表信息2.同一按钮在1秒内只会响应一次点击事件ScrollView中嵌套ListViewfragment之间跳转计时器倒计时跳转 踩过的坑顶部出现空白 2.服务端3.前后端通信3.1先学会最简单的,传string过去,返回string。mysql数据库中随机查询出5条数据进行测试的sql编写看的书叫:第一行代码 第二版 ,在微信读书(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-/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="/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><Buttonandroid: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="/apk/res/android"package="com.example.myapplication"><applicationandroid: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"><activityandroid: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";@Overrideprotected 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(){@Overridepublic 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="/apk/res/android"><itemandroid:id="@+id/add_item"android:title="Add"/><itemandroid:id="@+id/remove_item"android:title="Remove"/></menu>
2.让菜单显示出来,在Activity中重写onCreateOptionsMenu()方法。
重写快捷键ctrl+o
MenuInflater :用来解析定义在menu 目录下的菜单布局文件的Inflate():就是将xml定义的一个布局找出来
@Overridepublic 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
@Overridepublic 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(){@Overridepublic void onClick(View view) {finish();}});
使用Intent在活动穿梭
点击应用图标后只能进入主活动,如何从主活动跳转到其他活动呢?
intent 英:目的 意图
使用显式Intent进行跳转
Intent(上下文,想要启动的目标活动)
在上下文下打开想要启动的目标活动
Intent(Context packageContext, Class<?> cls)
button_1.setOnClickListener(new View.OnClickListener(){@Overridepublic 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过滤器节点,给目标活动配置(跳转目标)
<activityandroid: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(){@Overridepublic void onClick(View view) {Intent intent = new Intent("a");//想启动能相应那串字的活动startActivity(intent);//启动目标这个对象}});
只有当action、category都匹配上,才能成功。
刚才只有一个action,能成功是因为category用的是默认的,接下来也同样配置一下category。
<activityandroid: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(){@Overridepublic void onClick(View view) {Intent intent = new Intent("a");//想启动能相应那串字的活动intent.addCategory("b");startActivity(intent);//启动目标这个对象}});
更多隐式Intent用法
展示一个网页
button_1.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {Intent intent = new Intent(Intent.ACTION_VIEW);//系统内置动作intent.setData(Uri.parse(""));startActivity(intent);//启动目标这个对象}});
intent的action是Intent.ACTION_VIEW,这是一个系统内置的动作。
setData()用于指定intent正在操作的数据,接收的是url。
调用系统拨号
button_1.setOnClickListener(new View.OnClickListener(){@Overridepublic 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(){@Overridepublic 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 {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.second_layout);Intent intent = getIntent();//获取用于启动SecondActivity数据更新后的IntentString 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(){@Overridepublic 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() {@Overridepublic 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")@Overrideprotected 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)
@Overridepublic 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():在活动由停止状态变为运行状态前调用。
该图片出自/u013476556/article/details/44976947
内存不足,数据恢复
内存不足可能回收stop时的活动,临时数据会丢失,用户会生气。
解决:
onSaveInstanceState()回调函数,保证回收之前一定被调用。
@Overrideprotected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);outState.putString("data_key","临时数据");}
这样就保存在Bundle对象里。
怎么恢复?每次onCreate()里面有Bundle参数,平时是null,如果回收前用onSaveInstanceState保存过的话,这个参数就会带之前保存过的数据,修改onCreate取出来即可。
@Overrideprotected 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 = “模式”
<activityandroid: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(){@Overridepublic void onClick(View view) {SecondActivity.actionStart(MainActivity.this,"data1","data2");}});
三、UI
最后再详细写吧,想用什么查一下就好了。
控件
红色为常用控件
图片来源:/wufen12334/article/details/53072538
TextView
显示文本信息
Button
按钮
EditText
输入和编译内容
ImageView
展示图片
ProgressBar
显示一个进度条,表示程序正在加载一些数据。
AlertDialog
在当前页面弹出一个对话框,这个对话框置顶于所有界面元素之上,能屏蔽掉其他控件的交互能力,可以警告,提示等。
ProgressDialog
在界面上弹出一个对话框,能屏蔽掉其他控件的交互能力,显示一个进度条,表示当前操作比较耗时,请等待。
自定义控件
基本布局
LinearLayout线性布局
RelativeLayout相对布局
FrameLayout帧布局
所有控件默认放在左上角
百分比布局
任意比例分割布局
开源UI框架
Side-Menu.Android 分类侧滑菜单
/Yalantis/Side-Menu.Android
AndroidSwipeLayout 滑动Layout
滑动Layout,支持单个View,ListView,GridView。
项目地址:
/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);@Overridepublic void onClick(View v) {long curClickTime = System.currentTimeMillis();if((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {// 超过点击间隔后再将lastClickTime重置为当前点击时间lastClickTime = curClickTime;onMultiClick(v);}}}
btn.setOnClickListener(new OnMultiClickListener() {@Overridepublic 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() {@Overridepublic 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服务这么写的:
@Controllerpublic class LoginInController {//将Service注入Web层@Autowiredprivate 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;