Android 开发常见问题

  • Post author:
  • Post category:其他




1、Android10及以上 无法创建文件夹

解决方法:
  1. 修改gradie 中sdk版本号 29以下

  2. 使用Android规定的文件夹

  3. 添加android:requestLegacyExternalStorage=”true”到清单中。存储模型发生改变,这样是选择旧式存储模型,并且现有的外部存储代码将起作用。然后动态添加ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION 权限



2、多权限动态申请

public void checkPermission() {
	ActivityCompat.requestPermissions(MainActivity.this,
	    new String[]{
	        Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA,
            Manifest.permission.SET_ALARM,
            Manifest.permission.CHANGE_NETWORK_STATE,
            Manifest.permission.CHANGE_WIFI_STATE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.READ_PHONE_STATE},
         111);
}

//回调
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 111) {
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    Tools.showToast(MainActivity.this, "缺少权限(" + permissions[i] + ")");
                    return;
                }
            }
        }
    }



3、AndroidStudio 4.0以上Swicth提示


Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using them in switch case statements

//4.0 以上提示 id可能会改变,所有不建议使用switch catch
Switch(view.getId()){
	case R.id.btb:
		//......
		break;
	case R.id.change:
		//......
		break;
	...
	...
}

//可以改用if else ,性能几乎没有影响
int id = view.getId();
if(id == R.id.btb){
	//...........
}else if(id == R.id.change){
	//...........
}...{
}...



4、Activity、Fragment之间的交互



1)Activity访问Fragment

如果Fragment是通过布局文件添加到activity中

//fragment是通过布局文件引入的
<fragment>
	android:tag="fragment_bottom_tag"
	android:id="@+id/fragment_bottom"
	android:name="com.demo.BottomFragment"
	android:layout_width="match_parent"
	android:layout_height="50dp"
	android:layout_alignParentBottom="true"/>
</fragment>

//则有两种方式可以获取到fragment
BottomFragment fragment = (BottomFragment)getFragmentManager().findFragmentById(R.id.fragment_bottom): //通过id
BottomFragment fragment = (BottomFragment)getFragmentManager().findFragmentById("fragment_bottom_tag");//通过tag

//获取fragment中的某个控件
if(fragment != null){
	fragment.getView().findViewById(R.id.text);
}

如果fragment 是通过new Fragment() 方式获取的,则直接通过变量名操作

<frameLayout
	id="@+id/fragment_container"
	android:layout_width="match_parent"
	android:layout_height="50dp" />
	
//将Fragment添加到layout中
BottomFragment fragment = new BottomFragment();
getFragmentManager().beginTransaction()
	.add(R.id.fragment_container,fragment).commit();

fragment.getView().findViewById(R.id.text);
	


2)Fragment访问Activity

方法一、通过getActivity()方法获取,但是这种方式不好

@Override
public void onActivityCreated(....){
	//方法一(这种方式不好)在fragment中获取activity控件
	CheckBox chkMarried = (CheckBox)getActivity().findViewById(R.id.chk_married);
	button.setOnClickListener(new OnClickListener(){
		@Override
			public void onClick(View view){
					if(chkMarried.isChecked){}
			}
	});
	//如果需要获取activity中的成员变量,只需要调用activity中的get()方法
}

方式二、通过创建回调函数来实现

Fragment与其附属着的activity之间的通信的最佳方式:

1、在发起事件的Fragment中定义一个接口,接口中声明你的方法

2、在onAttach方法中要求activity实现这个接口

3、在Activity中实现该方法

1、在fragmeng中定义接口
public interface OnNewItemAddListener{
	public void newItemAdded(String content);
}
2、声明接口引用变量
private OnNewItemAddListener onNewItemAddListener;
3、在fragment的onAttach方法中要求activity实现这个方法
@Override
public void Attach(Activity activity){
	super.onAttach(activity);
	//要求该ftragment所附着的Activity必须完成这个方法的实现
	try{
		onNewItemAddListener = (OnNewItemAddListener) activity;
	}catch(ClassCastException e){
	}
}
4、在fragment中 需要的事件内 调用接口方法
onNewItemAddListenter.newItemAdded("");

5、在activity中必须实现接口
public class IndexActivity extends Activity implements OnNewItemAddListener{
	。。。
	。。。
	@Override
	public void newItemAdd(String content){
		//操作fragment传过来的content
	}
}



3)所有Fragment之间的通信

所有Fragment之间的通信,都应该通过他们所属的Activity来完成,不能是多个Fragment之间的直接通信、调用(尽管可以)



5、JAVA-startActivityResult 替代

用registerForActivityResult替代即可

ActivityResultLauncher launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                //此处是跳转的result回调方法
                if (result.getData() != null && result.getResultCode() == Activity.RESULT_OK) {
                    Tools.showToast(context,"返回成功");
                } else {
                    Tools.showToast(context,"返回失败");
                }
            }
        });


注意:registerForActivityResult的初始化需要在onCreate中进行

调用

Intent intent = new Intent(context, Second.class);
 launcher.launch(intent);



6、DataBinding 提示找不到类

在布局文间中引入类后:

<data>
        <variable
            name="idol"
            type="com.kaiya.mvp.jetpacktest.DataBindingF.Idol" />
    </data>

提示找不到

“com.kaiya.mvp.jetpacktest.dataBindingF.Idol”



原因:


Gradle4.6版本升级之前,包文件名首字母大小写都可以,升级以后文件名必须小写字母开头。所以需要将包文件名首字母改为小写

如下代码,将

“DataBindingF”

改为

“dataBindingF”

<data>
        <variable
            name="idol"
            type="com.kaiya.mvp.jetpacktest.dataBindingF.Idol" />
    </data>



7、DataBinding 提示 Cause: couldn’t make a guss for

在引入事件类时

<variable
	name="eventHandle"
	type="com.kaiya.mvp.jetpacktest.dataBindingF.eventHandleListener" />

提示

“使用dataBinding报错:Cause: couldn‘t make a guess for的解决办法”


原因:



是类名没遵循大驼峰命名法(首字母大写)导致的


(eventHandleListener 首字母没有大写)

改成首字母大写就好了:

<variable
	name="eventHandle"
	//eventHandlerListener 首字母改为大写了 -> EventHandlerListener
	type="com.kaiya.mvp.jetpacktest.dataBindingF.EventHandleListener" /> 



8、ViewBinding 与 DataBinding区别

https://developer.aliyun.com/article/938714



版权声明:本文为xianKOG原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。