安卓日常学习遇到的问题解决 使用SharedPreferences
来存储数据 1.Context 类中的 getSharedPreferences()
方法
第一个参数用于指定 **SharedPreferences
**文件的名称,如果指定的文件
不存在则会创建一个 ,SharedPreferences
文件都是存放在/data/data//shared_prefs/
目录下的。第二个参数用于指定操作模式,目前只有 MODE_PRIVATE这一种模式可选,它是默
认的操作模式,和直接传入 0 效果是相同的,表示只有当前的应用程序才可以对这个
SharedPreferences
文件进行读写。
2.Activity 类中的 getPreferences()
方法
只接收一个操作模式参数 ,因为使用这个方法时会自动将当前活动的类名作为 SharedPreferences
的文件名。
3.PreferenceManager
类中的 getDefaultSharedPreferences()
方法
这是一个静态方法,它接收一个 Context
*参数 ,并自动使用 *当前应用程序的包名作为前缀
来命名 SharedPreferences
文件
注:每个应用都有一个默认的配置文件preferences.xml,使用getDefaultSharedPreferences
获取。
存储数据
(1) 调用SharedPreferences
对象的 edit() 方法来获取一个 SharedPreferences.Editor
对象。
(2) 向 SharedPreferences.Editor
对象中添加数据,比如添加一个布尔型数据就使用
putBoolean()
方法,添加一个字符串则使用 putString()
方法,以此类推。
(3) 调用 apply()
方法将添加的数据提交,从而完成数据存储操作。
获取数据
通过 getSharedPreferences()
方法得到了 SharedPreferences
对象,然后分别调用它的 getString() 、 getInt() 和 getBoolean()
方法,去获取前面所存储
removeAllViews()
和removeAllViewsInLayout()
的区别removeAllViews()
: 从ViewGroup
中移除所有子视图
removeAllViewsInLayout()
: ViewGroup
的子类调用,移除自身的子视图,但在它能计算多少子视图被渲染前, 必须首先知道它在屏幕中尺寸。
在有些情况下,removeAllViews()
能移除掉子视图,但removeAllviewsInLayout()
移除不掉,因为子视图还未计算。
Fragment中addToBackStack()
使用 addToBackStack(null)
:调用该方法后,每次替换新的fragment,旧的fragment都被添加到回退栈中,当按返回键时,将之前的fragment恢复。 可以用于将一个事务添加到返回栈中。
用于解决两个Fragment之间按返回键直接退出activity的问题(即无法返回上一个Fragment )
ViewPager
就是一个简单的页面切换组件,我们可以往里面填充多个View,然后我们可以左 右滑动,从而切换不同的View,我们可以通过setPageTransformer()
方法为我们的ViewPager
设置切换时的动画效果。
让SDK版本高于27的项目可以使用http请求,解除安全限制。 创建xml文件,标签为网络安全设定
1 2 3 4 5 <network-security-config > <base-config cleartextTrafficPermitted ="true" /> </network-security-config >
还需要在AndroidManifest.xml文件中进行引用
1 android:networkSecurityConfig="@xml/network_security_config"
优化切换动画 自定义ViewPage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class FixedViewPager extends ViewPager { public FixedViewPager (@NonNull Context context) { super (context); } public FixedViewPager (@NonNull Context context, @Nullable AttributeSet attrs) { super (context, attrs); } @Override public void setCurrentItem (int item) { super .setCurrentItem(item,false ); } }
super.setCurrentItem(item,false);
当第二个参数为false时,切换页面时的缓慢的滑动效果消失,变成快速切换。
1 2 viewPager.setOffscreenPageLimit(mFragments.size());
播放器解决全屏时出现闪退问题,让其生命周期不发生变化 1 2 3 4 5 6 <activity android:name =".activity.HomeActivity" android:configChanges ="orientation|screenSize|keyboardHidden" android:screenOrientation ="portrait" > </activity >
使用handle完成与主线程沟通。和runOnUiThread
是同样的作用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 private Handler mhandle = new Handler () { @Override public void handleMessage (@NonNull Message msg) { super .handleMessage(msg); switch (msg.what) { case 0 : videoAdapter.setDatas(datas); videoAdapter.notifyDataSetChanged(); break ; } } };
登录成功后,要清除回退栈,防止点击回退键回到登录页面。
1 2 3 4 5 6 7 8 9 10 11 12 navigateToWithFlag(HomeActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); showToastSync("登录成功" ); public void navigateToWithFlag (Class cls, int flags) { Intent intent = new Intent (mContext, cls); intent.setFlags(flags); startActivity(intent); }
安卓运行报错114:25: AAPT: error: resource android:attr/lStar not found.
原因是一开始创建的app中的 **build.gradele
**中的版本依赖过高 。下面是较低版本。
1 2 3 4 5 6 implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
RecycleView
中没有针对item的点击事件,需要自行创建一个接口。特别是需要跳转到activity情况写一个接口
1 2 3 public interface OnItemClickListener { void onItemClick (Serializable obj) ; }
在adapter中声明该OnItemClickListener
接口类,设置一个传参方法。
1 2 3 4 private OnItemClickListener mOnItemClickListener;public void setOnItemClickListener (OnItemClickListener onItemClickListener) { mOnItemClickListener = onItemClickListener; }
在控件点击事件中调用该接口类方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 newsAdapter.setOnItemClickListener(new NewsAdapter .OnItemClickListener() { @Override public void onItemClick (Serializable obj) { NewsEntity newsEntity = (NewsEntity) obj; String url = "http://10.211.29.252:8089/newsDetail?title=" + newsEntity.getAuthorName(); Bundle bundle = new Bundle (); bundle.putString("url" , url); navigateToWithBundle(WebActivity.class, bundle); } });
1 add(0 , node.val);在列表的指定位置插入指定元素(可选操作)。将当前处于该位置的元素(如果有的话)和所有后续元素向右移动(在其索引中加 1 )。
AndroidMainfest.xml中的android.support.v4.content.FileProvider爆红 使用打开相机拍照时, 使用到FileProvider
则是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性地将封装过的 Uri共享给外部。使用FileProvider
时在AndroidMainfest.xml中注册
解决方式:需要将其换成androidx.core.content.FileProvider
1 2 3 4 5 6 7 8 9 <provider android:authorities ="com.example.cameraalbumtest.fileprovider" android:name ="android.support.v4.content.FileProvider" android:exported ="false" android:grantUriPermissions ="true" > <meta-data android:name ="android.support.FILE_PROVIDER_PATHS" android:resource ="@xml/file_paths" /> </provider >
file_paths.xml中的path爆红(不算问题) 这里爆红不影响程序运行。
去掉EditText
的下划线直接将android:background="@null"
安卓按比例进行布局 将子View的宽度或是高度设为0,然后为子View设置不同权重(weight) ,这样子View的大小就会权值成比例。
本例使用横向LinearLayout
,LinearLayout
的android:layout_width=”match_parent”
,表示将使用整个屏幕宽度。
对于LinearLayout
的几个子View,将它们的宽度都定义为0,android:layout_width="0dip"
,然后使用layout_weight 为每个View指定宽度比例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <Button android:id ="@+id/note" android:layout_width ="0dp" android:layout_height ="100dp" android:layout_weight ="1" android:text ="笔记" > </Button > <Button android:id ="@+id/target" android:layout_width ="0dp" android:layout_height ="100dp" android:layout_weight ="1" android:text ="代办" />
Android EditText
输入回车符自动跳转至下一个EditText
在输入信息时,在EditText
控件输入回车键,经常不是换行二十让光标直接跳转到下一个编辑框。该功能主要用到了文本监听器借口 **TextWatcher
**,主要监听用户是否输入回车符,若是监听到已输入回车符,就自动将焦点移动到下一个控件,从而实现回车符自动跳转的要求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class MainActivity extends AppCompatActivity { EditText editText1,editText2; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText1=(EditText)findViewById(R.id.editText1); editText2=(EditText)findViewById(R.id.editText2); editText1.addTextChangedListener(new JumpTextWatcher ()); } private class JumpTextWatcher implements TextWatcher { @Override public void beforeTextChanged (CharSequence s, int start, int count, int after) { } @Override public void onTextChanged (CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged (Editable s) { String str=s.toString(); if (str.indexOf("\r" )>=0 || str.indexOf("\n" )>=0 ){ editText1.setText(str.replace("\r" ,"" ).replace("\n" ,"" )); editText2.requestFocus(); editText2.setSelection(editText2.getText().length()); } } } }
如何用su
命令切换成超级管理员 输入adb.shell
如何显示$
代表我们是普通管理员,需要通过su
命令切换成超级管理员。但是提示/system/bin/sh: su: not found
其实这个问题是因为我们用的模拟器,带有了Googel play
是不允许获得管理员权限。下载一个Target是Google APIS的模拟器,打开AVD Manager,选择创建一个新的设备并给它更换镜像。
Android中删除EditText
中内容时报SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 在使用Android中的EditText
时,若在对应APP窗口中删除文本框 中的内容或移动光标位置时,会出现如下错误:
在对应EditText
下添加 android:inputType=“textNoSuggestions”
属性即可
在使用DrawerLayout
关闭菜单时 1 closeDrawer(@DrawerLayout .EdgeGravity int gravity)
Gravity.LEFT
移动左侧抽屉或 Gravity.RIGHT
向右移动。也可以使用 GravityCompat.START
或 GravityCompat.END
。
安卓启动不了,安卓必须要先安装好jdk
并配置好环境 NDK版本对不上,只需在SDK Manager 中添加即可 Error: open failed: ENOENT (No such file or directory) 当用户从图库中选择文件时,不能保证选择的文件是由其他应用程序添加或编辑的。因此,如果用户选择了一个属于另一个应用程序的文件,我们就会遇到权限问题。对此的快速解决方法是在 AndroidManifest.xml 文件中添加以下代码:
1 2 3 4 5 <manifest ... > <application android:requestLegacyExternalStorage ="true" ... > ... </application > </manifest >
Android之NetworkOnMainThreadException异常 网络请求在MainThread中产生的异常,网络请求尽量用RxJava异步请求。
抛出java.lang.IllegalArgumentException: Missing either @POST URL or @Url parameter. **该异常是指@**POST内容为空
解决办法直接在其中加上 没有数据就加 . 或者 /
1 2 3 @POST(".") Observable<FeedBackBean> feedbacklist (@Field("postinfo") String postinfo);
viewpage里面可以嵌套recycleview,可以单独创建出来一个view出来,然后adapter中放入new出来的recycleview。 recycleView置顶item 1 2 3 mLinearLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLinearLayoutManager); mLinearLayoutManager.scrollToPositionWithOffset(position, 0);
switch控件使用 1 2 3 4 5 6 7 8 9 10 11 // 点击事件 mSwitchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { // 选中状态 (更改显示信息, 保存设置到sp...) } else { // 未选中状态 (更改显示信息, 保存设置到sp...) } } });
出现Cannot resolve symbol ‘@+id/follow_list’ ,直接rebuild项目即可 Android volley error: “Trust anchor for certification path not found”, only in real device, not emulator 该错误是对于一些手机再进行使用选择照片功能时,出现的SSL证书错误,只需要允许通过所有证书即可
将这段代码添加到程序中,在onCreate之后调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /** * Enables https connections */ @SuppressLint("TrulyRandom") public static void handleSSLHandshake() { try { TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { } }}; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); } catch (Exception ignored) { } }
请求码为-2则表示传入的参数有问题,一般要传入json格式。from-data在登录的时候才使用。 list接口之后所有方法都不能传入null integer 相比于int类型可以为空,在RxJava中不允许integer 或任意数据为空的情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 Observable.just(1 ) .subscribeOn(Schedulers.newThread()) .map(new Func1 <Integer, Boolean>() { @RequiresApi(api = Build.VERSION_CODES.N) @Override public Boolean call (Integer integer) { tempFriendsListResults = GetFriendsListProtocol.getFriendsList(new FriendsList (20 , page)); Log.v("loadData" , "运行" + page); if (tempFriendsListResults != null ) { if (friendsListResults != null && currentPage == 1 ) { friendsListResults.clear(); } Log.v("loadDataInside" , "运行" ); Map<String, List<FriendsListResult>> map = tempFriendsListResults.stream().sorted(Comparator.comparing(FriendsListResult::getNickname)) .collect(Collectors.groupingBy(FriendsListResult::getOnlineStatus, Collectors.toList())); Log.v("loadDataInside" , "sort" ); if (map.get("Online" ) != null ) { friendsListResults = map.get("Online" ); if (map.get("Incall" ) != null ) { friendsListResults.addAll((Objects.requireNonNull(map.get("Incall" )))); } if (map.get("Busy" ) != null ) { friendsListResults.addAll(Objects.requireNonNull(map.get("Busy" ))); } if (map.get("Offline" ) != null ) { friendsListResults.addAll(Objects.requireNonNull(map.get("Offline" ))); } } else if (map.get("Incall" ) != null ) { friendsListResults = map.get("Incall" ); if (map.get("Busy" ) != null ) { friendsListResults.addAll(Objects.requireNonNull(map.get("Busy" ))); } if (map.get("Offline" ) != null ) { friendsListResults.addAll(Objects.requireNonNull(map.get("Offline" ))); } } else if (map.get("Busy" ) != null ) { friendsListResults = map.get("Busy" ); if (map.get("Offline" ) != null ) { friendsListResults.addAll(Objects.requireNonNull(map.get("Offline" ))); } } else if (map.get("Offline" ) != null ) { Log.v("loadDataInside" , "inside?" ); friendsListResults = map.get("Offline" ); } if (tempFriendsListResults != null ) { tempFriendsListResults.clear(); } return true ; } else { Log.v("loadDataInside" , "数据为空?" ); return false ; } } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1 <Boolean>() { @Override public void call (Boolean aBoolean) { if (aBoolean) { if (followAdapter != null ) { followAdapter.notifyDataSetChanged(); Log.v("loadDataInside" , "notify" ); } Log.v("loadDataInside" , "refresh" ); followedXRefreshView.stopRefresh(true ); followedXRefreshView.stopLoadMore(); } else { followedXRefreshView.stopRefresh(false ); followedXRefreshView.stopLoadMore(); } } }, new Action1 <Throwable>() { @Override public void call (Throwable throwable) { Log.v("loadDataInside" , throwable.getMessage()); followedXRefreshView.stopRefresh(false ); followedXRefreshView.stopLoadMore(); } });
Android Jetpack: 从androidx包中导入的类引用Jetpack库。在构建中对Jetpack的依赖。Gradle文件也从androidx开始。
kotlin 中关键字 lateinit 需要在最外面声明一个变量时,如果直接将该变量设置为空,则每次初始化该变量时都需要判空。如果直接声明成lateinit的变量,如果在整个代码里面都没有进行任何的初始化,那么能否编译通过?如果你加上了lateinit关键字,kotlin的编译器 不会做这种检查。如果你将变量声明为lateinit,它就认为你肯定会初始化,至于你是怎么初始化它的,它就不管了
总结:
lateinit 延迟加载
2.lateinit 只能修饰, 非kotlin基本类型
3如果你的代码真的显示初始化了lateinit变量,而又抛出了UninitializedPropertyAccessException异常, 因为你恰好将变量初始化为null了
因为Kotlin会使用null来对每一个用lateinit修饰的属性做初始化,而基础类型是没有null类型,所以无法使用lateinit。
使用 Stack Overflow程序员社区搜索问题 进入Stack Overflow。
在搜索框中输入“如何通过Wi-Fi设置和使用ADB ?”你可以不注册就在Stack Overflow上搜索,但如果你想发布一个新问题或回答一个问题,你需要注册。
在搜索框中输入[android]。括号中的[]表示您想要搜索已标记为关于Android的文章。
您可以结合标签和搜索词,使您的搜索更具体。试试这些搜索:
(android)和(layout)
(android)“hello world”
在项目级的build gradle中可以查看当前项目是app类型还是library类型,library类型就必须要依赖进入项目中才可以使用,等同sdk Kotlin插件更新错误 please update kotlin plugin
正常在使用if判断更改界面文字样式等,记得要加上else判断特殊情况,防止出错。即使是空的也行。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if (position < promotionList.size() && !promotionList.isEmpty()) { String date = DateUtil.getDate("hh:mm:ss" , goodsResults.get(promotionList.get(position)).getSurplusMillisecond()); holder.tag.setText(date); GradientDrawable gradientDrawable = new GradientDrawable (); gradientDrawable.setOrientation(GradientDrawable.Orientation.TOP_BOTTOM); holder.tag.setBackground(QuickDrawable.create() .bgColor(gradientDrawable.getOrientation(), new int []{Color.parseColor("#513dfb" ), Color.parseColor("#730ffe" )}) .corner(DeviceUtils.dip2px(8 ), 0 , 0 , DeviceUtils.dip2px(8 )) .build()); holder.mBgLayout.setBackgroundResource(R.drawable.shape_store_blue); }else { }
在需要实时刷新改变的recycleView等列表,因为其一般只显示能看见的几个item,因此他的position值是一直改变的。 因此最好在绑定数据时,先设置一个默认的界面数据,在进入判断时,再进行改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 holder.mBgLayout.setBackgroundResource(R.drawable.shape_store_white); holder.discount.setText("" ); holder.tag.setText("" ); holder.tag.setBackground(null ); holder.icon.setText(goodsResults.get(position).getExchangeCoin().toString()); holder.price.setText("$" + goodsResults.get(position).getPrice().toString()); if (!goodsResults.get(position).getDiscount().toString().equals("0.00" )) { holder.discount.setText(goodsResults.get(position).getDiscount().toString() + "%off" ); } if (position < promotionList.size() && !promotionList.isEmpty()) { String date = DateUtil.getDate("hh:mm:ss" , goodsResults.get(promotionList.get(position)).getSurplusMillisecond()); holder.tag.setText(date); GradientDrawable gradientDrawable = new GradientDrawable (); gradientDrawable.setOrientation(GradientDrawable.Orientation.TOP_BOTTOM); holder.tag.setBackground(QuickDrawable.create() .bgColor(gradientDrawable.getOrientation(), new int []{Color.parseColor("#513dfb" ), Color.parseColor("#730ffe" )}) .corner(DeviceUtils.dip2px(8 ), 0 , 0 , DeviceUtils.dip2px(8 )) .build()); holder.mBgLayout.setBackgroundResource(R.drawable.shape_store_blue); } if (goodsResults.get(position).getTags() != null && !goodsResults.get(position).getPromotion()) { if (!goodsResults.get(position).getTags().isEmpty()) { holder.tag.setText(goodsResults.get(position).getTags()); GradientDrawable gradientDrawable = new GradientDrawable (); gradientDrawable.setOrientation(GradientDrawable.Orientation.TOP_BOTTOM); holder.tag.setBackground(QuickDrawable.create() .bgColor(gradientDrawable.getOrientation(), new int []{Color.parseColor("#513dfb" ), Color.parseColor("#730ffe" )}) .corner(DeviceUtils.dip2px(8 ), 0 , 0 , DeviceUtils.dip2px(8 )) .build()); Log.v("tagbiaoqian" ,position+" " +goodsResults.get(position).getTags()); } }
android studio 在新版本必须要求使用Gradle JDK 11 版本,否则会出现报错 1 execution failed for task ':app:kapthost release debug kotlin' . > a failure occurred while executing org.jetbrains.kotlin.gradle.internal.kaptwithoutkotlinctask$kaptexecutionworkaction > java.lang.reflect.invocationtargetexception (no error message)
问题原因 :
出现该问题的原因主要是因为使用Android Studio 4.1之后的版本进行开发时 ,创建的项目默认的主题所有Button都是Material类型的Button ,默认使用主题色,所以想要修改颜色,就要把默认主题给关了或替代了 。
解决方法:
方式一:
<Button
android:id=”@+id/button4”
改为——–>
<android.widget.Button
android:id=”@+id/button4”
方式二:
找到temes.xml文件
将这段代码:
1 <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar" >
修改为:
1 <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge" >