Android应用层开发碎片知识

Android应用层开发碎片知识

startActivityForResult

应用场景

比如从AActivity跳转到BActivity,然后在BActivity中做一系列操作,然后在BActivity关闭时候需要把一些数据再回传给AActivity,或者当BActivity关闭后,需要让AActivity的界面或者数据发生一些变化。

示例代码

startActivityForResult(
    new Intent(MainActivity.this, LoginActivity.class),
    Constants.RequestCode.REQUEST_CODE_LOGIN);

以上代码表示从MainActivity跳转至LoginActivity,当LoginActivity关闭后将Constants.RequestCode.REQUEST_CODE_LOGIN传回给MainActivity。

Rxjava

Disposable类

  • dispose():主动解除订阅
  • isDisposed():查询是否解除订阅 true 代表 已经解除订阅

示例代码

// 创建一个Disposable
Disposable mDisposable = Observable
    // 每间隔延迟1s发送一次数据
    .interval(0, 1L, TimeUnit.SECONDS)
    // 将发送的数据按map中的计算式计算后返回
    .map(new Function<Long, Long>() {
    	@Override
        public Long apply(Long countDownSecond) {
        	return retrySecond - countDownSecond;
        }
     })
    // 在io线程中发送消息
     .subscribeOn(Schedulers.io())
    // 在主线程中接收消息
     .observeOn(AndroidSchedulers.mainThread())
    // 在onNext()每次发送完消息后的操作
     .doOnNext(new Consumer<Long>() {
     	@Override
        public void accept(Long aLong) {
        	mBtnConfirm.setVisibility(View.GONE);
        	mBtnConfirm.setFocusable(false);
            mBtnCancel.setText(getStrings(R.string.dialog_cancel));
            mBtnCancel.requestFocus();
        }
      })
      // 接收消息
      .subscribe(new Consumer<Long>() {
       @Override
       public void accept(Long currSecond) {
       		...
       });
         
// 判断是否解除订阅
if(!mDisposable.isDisposable()){
    mDisposable.disposable(); // 如若没有解除订阅则解除订阅
}

CompositeDisposable

一个disposable的容器,可以容纳多个disposable,添加和去除的复杂度为O(1)。

如果这个CompositeDisposable容器已经是处于dispose的状态,那么所有加进来的disposable都会被自动切断。

用CompositeDisposable来管理订阅事件disposable,然后在acivity销毁的时候,调用compositeDisposable.dispose()就可以切断所有订阅事件,防止内存泄漏。

示例代码

CompositeDisposable mDisposable = new CompositeDisposable();

// 添加disposable
mDisposable.add(disposable);

// 移除一个disposable
mDisposable.remove(disposable);

// 移除所有的disposable
mDisposable.clear();

DialogFragment

调用show()方法即可显示dialog,调用dismiss()方法即可取消dialog的显示。

基类 BaseDialogFragment

一般先写一个基类继承于Dialogfragment,再由具体的业务需求创建具体的DialogFragment继承基类。

基类中一般需要写以下几个方法,onCreateView()创建显示dialog所在的view;onCreateDialog()创建自定义的dialog;onViewCreated()依据自定义的xml创建view。

示例代码如下:

public abstract class BaseDialogFragment extends DialogFragment {
    
    protected BaseActivity mActivity;
    private Unbinder mUnBinder;
    private View mRootView;
    
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof BaseActivity) {
            this.mActivity = (BaseActivity) context;
        }
    }
    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRootView = inflater.inflate(getLayoutId(), container, false);
        mUnBinder = ButterKnife.bind(this, mRootView);
        return mRootView;
    }
    
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        RelativeLayout root = new RelativeLayout(getActivity());
        root.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        Dialog dialog = new Dialog(getContext());
        dialog.setCancelable(true);
        dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                return onKeyListener(dialog, keyCode, event);
            }
        });
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(root);
        dialog.getWindow().setLayout(resizeDialogWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
        return dialog;
    }
    
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        mRootView.requestFocus();
        setup(view);
        super.onViewCreated(view, savedInstanceState);
    }
    
    @Override
    public void show(FragmentManager manager, String tag) {
        // 开启Fragment事务
        FragmentTransaction transaction = manager.beginTransaction();
        // 依据Tag获取Fragment
        Fragment fragment = manager.findFragmentByTag(tag);
        if (fragment != null) {
            /*
             Fragment被remove后,Fragment的生命周期会一直执行完onDetach,之后Fragment的实例也会从FragmentManager中移除。
            */
            transaction.remove(fragment);
        }
        /*
        将此事务添加到后台堆栈。这意味着该事务被提交后将会被记住后,回退操作后,事务会从堆栈中弹出。*/
        transaction.addToBackStack(null);
        show(transaction, tag);
    }
    
    @Override
    public void onDestroyView() {
        if (mUnBinder != null) mUnBinder.unbind();
        super.onDestroyView();
    }

    @Override
    public void onDetach() {
        mActivity = null;
        super.onDetach();
    }
    
    /**
     * 监听响应事件
     */
    protected boolean onKeyListener(DialogInterface dialog, int keyCode, KeyEvent event) {
        return false;
    }

    protected abstract int getLayoutId();

    /**
     * 对话框创建后,在该方法修改对话框布局的某些view
     */
    protected abstract void setup(View view);
}

transaction.addToBackStack(null);

  • 第1次按下手机的back键,其实是回退了之前的add操作,如果再FragmentManager中没有add任何Fragment,程序没有退出而是变成了白板。
  • 第2次按下手机的back键,因为当前回退栈已空,addToBackStack中添加的是null,程序就直接退出了。

Handling Lifecycles

Handling Lifecycles包含的主要内容:
1.Lifecycle
2.LifecycleObserver
3.LifecycleOwner

LifecycleObserver

简单介绍

  • 定义具有Android生命周期的对象
  • v4包的Fragment与FragmentActivity类实现了LifecycleOwner接口,通过接口里面的getLifecycle()方法获取Lifecycle对象。
  • 我们可以在自己类里面实现LifecycleOwner接口。
  • 包含事件Events与状态States

示例代码

定义一个实现Lifecycles接口的基类BasePresenter

public class BasePresenter<T> implements LifecycleObserver {
    private CompositeDisposable mDisposable = new CompositeDisposable();
    protected T mView;

    public BasePresenter(T view) {
        this.mView = view;
    }

    protected void addObserver(@NonNull Disposable disposable) {
        mDisposable.add(disposable);
    }

    protected void removeObserver(@NonNull Disposable disposable) {
        mDisposable.remove(disposable);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    protected void release() {
        mDisposable.clear();
        mView = null;
    }
}

定义一个具体的AuthPresenter,继承BasePresenter,用注解的方式表明那个方法在Activity不同的生命周期运行,代码如下:

public class AuthPresenter extends BasePresenter{
    ....
        public AuthPresenter(AuthContract.View view) {
        super(view);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    private void handleMultiError() {
        RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) {
                Log.i(TAG, throwable.getMessage());
            }
        });
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    @Override
    public void registerNetwork() {
        Context context = (Context) mView;
        mNetworkObserver = new NetworkObserver(context);
        mNetworkObserver.registerNetworkReceiver();
        mNetworkObserver.setNetworkListener(this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    @Override
    public void unregisterNetwork() {
        if (mNetworkObserver != null) {
            mNetworkObserver.unregisterNetworkReceiver();
        }
    }
    .....
}

在需要监听它生命周期的activity中加入getLifecycle().addObserver(new AuthPresenter()),示例代码如下:

public class MainActivity extends BaseActivity{
    
    private AuthPresenter mPresenter;
    
    @Override
    protected void setup() {
        mPresenter = new AuthPresenter(this);
        getLifecycle().addObserver(mPresenter);
    }
    ....
}

LifecycleOwner

基类实现implements LifecycleOwner接口,然后实现getLifecycle,当然LifecycleRegistry这个类是官方提供的默认事件注册类,最后在你想要监听的生命周期中通知mLifecycleRegistry.markState,生命周期改变。

示例代码如下:

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    }
 
    @Override
    public void onStart() {
        super.onStart();
        mLifecycleRegistry.markState(Lifecycle.State.STARTED);
    }
 
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

android应用程序中启动另一个应用程序

new Intent(xxxActivity.this, xxxActivity.class)

// 在Activity中执行
startActivity(new Intent(getApplication(),xxxActivity.class));

//在类中执行
if(getContext() != null){
    startActivity(new Intent(getContext().getApplicationContext(), 
                            xxxActivity.class));
}

intent.setComponent(String …str)

不仅可以启动自定义的应用程序,也可启动系统的应用程序。new Component的构造法中第一个参数是启动应用的包名,第二个参数是启动应用的类名。

Intent intent = new Intent();
intent.setComponent(new Component("com.android.settings", "com.android.settings.Settings"));
// 在Activity中执行
startActivity(intent);

// 如若在类中执行
if(getContext() != null){
    getContext().startActivity(intent);
}

intent.setFlags()

示例代码:

Intent intent = new Intent();
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);

以下是各个参数的具体含义

FLAG_ACTIVITY_NEW_TASK

应用场景:
从非Activity的非正常途径启动一个Activity。

工作流程:
如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。
因为activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈,所以要新起一个栈装入启动的activity

FLAG_ACTIVITY_CLEAR_TOP

​ 跳转到的activity若已在栈中存在,则将其上的activity都销掉。
​ 例如现在的栈情况为:A B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B。

FLAG_ACTIVITY_NO_HISTORY

​ 跳转到的activity不压在栈中。
​ 例如现在栈情况为:A B C。C通过intent跳转到D,这个intent添加FLAG_ACTIVITY_NO_HISTORY标志,则此时界面显示D的内容,但是它并不会压入栈中。如果按返回键,返回到C,栈的情况还是:A B C。

FLAG_ACTIVITY_SINGLE_TOP

和Activity的Launch mode的singleTop类似。目标activity已在栈顶则跳转过去,不在栈顶则在栈顶新建activity。

Android Studio怎样设置SDK的路径

1. 用File修改

打开Android studio,点击“File”菜单下的“Other Settings”,接着点击“Default Project Structure”选项。

这时就会看到SDK Location,点击图示第二个红色区域的图标,就可以修改默认的AndroidSDK路径。

2. 启动Android Studio用Config修改

选择“Configure”,选择"Project Defaults",弹出设置默认工程的SDK路径

3. 修改路径时会出现的错误

  • SDK文件夹下面要有platforms文件夹,不然出现Android Studio报错:SDK does not contain any platforms.
  • SDK文件夹所在目录不能有空格,否则会出现报错,Android SDK location should not contain whitespace, as this can cause problems with the NDK tools.

A system image must be selected to continue

在这里插入图片描述

在启动项目建立虚拟设备时报错,表示系统图像不连续,下载Recommended列中的一些系统图片即可,如图中的Q,Pie,Oreo等。

导入com.android.support:percent:24.2.1包报错

**报错信息:**在app文件夹下build.gradle导入代码

depedencies{
	....
    imlementation 'com.android.support:percent:24.2.1'
    .....
    }

Sync后显示错误

All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 26.0.0-alpha1, 24.2.1. Examples include com.android.support:animated-vector-drawable:26.0.0-alpha1 and com.android.support:percent:24.2.1 less... (Ctrl+F1) 
There are some combinations of libraries, or tools and libraries, that are incompatible, or can lead to bugs. One such incompatibility is compiling with a version 

问题的原因

简单来说就是所有com.android支持库必须使用完全相同的版本规范,混合版本可能导致运行时崩溃。现在对应的Android SDK版本过高,需要下载更低一版的SDK才能兼容com.android.support:percent:24.2.1

有一些库、工具和库的组合是不兼容的,或者可能导致bug。

解决办法

找到android SDK的文件夹I:\AndroidSDk\extras\android\m2repository\com\android\support\percent
在这里就能看到各种版本的percent,选择合适的版本进行导入。

如果找不到这个文件夹,在Android Studio中的file->setting->System Settings->Android SDK,选择下载较为常用的sdk4,5,6,7版本,再来导入此包。

read failed: EBADF

**具体报错信息:**java.io.IOException: read failed: EBADF (Bad file number)。

**报错原因:**这是由于在java中执行命令行命令后没有写入\n,导致读取命令行执行结果时报错。

解决示例代码如下:

String command = "ping baidu.com";
Process p = Runtime.getRuntime().exec("sh"); // 获取系统权限
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
            dos.write(command.getBytes());
            dos.writeBytes("\n");
            dos.writeBytes("exit\n");
            dos.flush();
int status = p.waitFor(); // 命令执行结果
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); // 命令执行输出结果
String line = null;
// 打印输出结果
while ((line = br.readLine()) != null) {
                Log.i(TAG, "ping: " + line);
}
发布了15 篇原创文章 · 获赞 0 · 访问量 232

猜你喜欢

转载自blog.csdn.net/lxy1740/article/details/104296043
今日推荐