Android+JetPack开发(持续更新)

本笔记基于B站视频教学以及安卓官方文档。BV号:BV1w4411t7UQ。受益匪浅,再次感谢。

Activity的生命周期

在这里插入图片描述

基本控件

MVC(Model-View-Controller)的设计模式。

TextView、Button、SeekBar、ImageView等等(参见开发者手册)。

点击事件:setOn...Listrner(new ...){...}

本地化Localization

更改系统语言,应用随之自动适配。

res->values->string.xml->Open Editor->Add Locale(左上角小地球)->Chinese zh

屏幕旋转

横向需要重新设置布局:Create Landscape Variationpubli

直接锁死竖屏:AndroidManifest.xml,<application><activity>中添加<android:screenOrientation="portrait">

ViewModel

减少不必要的代码冗余,使数据处理与UI分离,利于数据保存。

新建JavaClass:public class MyViewModel extends ViewModel {...}

MainActivity:

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    ...;
    
    @override
    public void onCreate(Bundle saveInstanceState) {
        super.onCreate(saveInstanceState);
        setContentView(R.layout.activity_main);
        
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);	//创建ViewModel对象
        ...;
    }
}

关于Bundle A mapping from String keys to various Parcelable values.

常用于Activity之间传递数据,并且数据存储形式key-value。

LiveData

官方解释:在底层数据库更改时通知视图。

在这里插入图片描述

*矢量图 New->Vector Asset(自带)。需要根据提示在Gradle里添加语句,否则会报错(与安卓API版本有关)。

新建ViewModel:

public class ViewModelWithLiveData extends ViewModel {
    private MutableLiveData<Integer> number;
    
    public MutableLiveData<Integer> getNumber() {
        if (Number == null) {	//number为对象类型,故要保证其非空
            number = new MutableLiveData<>();
            number.setvalue(0);
        }
        return number;
    }
    public void addNumber(int n) {
        number.setValue(number.getValue() + 1);
    }
}

MutableLiveData<>:LiveData which publicly exposes setValue(T) and postValue(T) method.

MainActivity:

public class MainActivity extends AppCompatActivity {
    ViewModelWithLiveData viewModelWithLiveData;
    ...;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ...;	//绑定等操作

        viewModelWithLiveData = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(ViewModelWithLiveData.class);
        viewModelWithLiveData.getNumber().observe(this, new Observer<Integer>() {//观察数据改变
            @Override	//this为具有LifeCycle管理功能的对象
            public void onChanged(Integer integer) {
                textView.setText(String.valueOf(integer));
            }
        });

        ...;	//按钮点击事件
    }
}

DataBinding

官方解释:以声明方式将可观察数据绑定到界面元素。

界面与代码的解耦。

在这里插入图片描述

build.gradle:

android {
	...
	defaultConfig {
		...
		dataBinding.enabled true
	}
}

跳转至layout.xml界面,第一行代码提示,点击Convert to databing layout

<data>
	<variable
     	name="data"
     	type="com.example.xxx.MyViewModel"/>
</data>

其中调用元素变量(数据回绑):android:text="@{String.valueOf(data.number)}",调用函数android:onClick="@{()->data.add()}"

注意 数据回绑调用需要声明为public

MainActivity:

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //实现数据的绑定与回绑
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        myViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);

        binding.setData(myViewModel);
        binding.setLifecycleOwner(this);
    }
}

ViewModelProvider() An utility class that provides ViewModels for a scope.

Default ViewModelProvider for an Activity or a Fragment can be obtained from ViewModelProviders class.

ViewModelProvider(ViewModelStoreOwner owner, ViewModelProvider.Factory factory)

ViewModelProvider.NewInstanceFactory() Simple factory, which calls empty constructor on the give class.

ViewModelSavedState

状态切换时的简单数据存储,使用SaveStateHandleSaveStateViewModelFactory()

SaveSateHandle SavedStateHandle 类是一个键值(key-value)对映射,用于通过 set()get() 方法向已保存的状态写入数据以及从中检索数据。

SaveStateViewModelFactory() ViewModelProvider.Factory that can create ViewModels accessing and contributing to a saved state via SavedStateHandle received in a constructor.

SaveStateViewModelFactory(Application application, SaveStateRegistryOwner owner)

MyViewModel:

public class MyViewModel extends ViewModel {
    private SavedStateHandle handle;

    public MyViewModel(SavedStateHandle handle) {
        this.handle = handle;
    }

    public MutableLiveData<Integer> getNumber() {
        if (!handle.contains(MainActivity.KEY_NUMBER)) {	//键值对应
            handle.set(MainActivity.KEY_NUMBER, 0);
        }
        return handle.getLiveData(MainActivity.KEY_NUMBER);
    }

	...;
}

MainActivity:

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    ActivityMainBinding binding;
    final static String KEY_NUMBER = "my_number";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        myViewModel = new ViewModelProvider(this, new SavedStateViewModelFactory(getApplication(), this)).get(MyViewModel.class);

        binding.setData(myViewModel);
        binding.setLifecycleOwner(this);
    }
}

SharedPreferences

简单数据的永久存储。

SharedPreferences shp = Context.getSharedPreferences(String, int)

MyData:(Model)

public class MyData {
    public int number;
    private Context context;

    public MyData(Context context) {
        this.context = context;
    }

    public void save() {
        String name = context.getResources().getString(R.string.MY_DATA);
        SharedPreferences shp = context.getSharedPreferences(name, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = shp.edit();
        String key = context.getResources().getString(R.string.MY_KEY);
        editor.putInt(key, number);
        editor.apply();
    }
    public int load() {
        String name = context.getResources().getString(R.string.MY_DATA);
        SharedPreferences shp = context.getSharedPreferences(name, Context.MODE_PRIVATE);
        String key = context.getResources().getString(R.string.MY_KEY);
        int x = shp.getInt(key, context.getResources().getInteger(R.integer.defValue));
        number = x;
        return x;
    }
}

Context This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.Context是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类。

该处用于MyData(其他类)获得MainActivity中的资源。

MainActivity:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        MyData myData = new MyData(getApplicationContext());    //不能传递this,可能导致内存泄漏
        myData.number = 1000;
        myData.save();
        int y = myData.load();
        String TAG = "myLog";
        Log.d(TAG, "onCreate" + y);
    }
}

AndroidViewModel

为ViewModel的子类,包含可直接访问context的方法。

Application context aware ViewModel.Subclasses must have a constructor which accepts Application as the only parameter.

getApplication()直接访问全局资源。

MyViewModel:

public class MyViewModel extends AndroidViewModel {
    private final SavedStateHandle handle;
    private final String key = getApplication().getResources().getString(R.string.data_key);
    private final String shpName = getApplication().getResources().getString(R.string.shp_name);

    public MyViewModel(@NonNull Application application, SavedStateHandle handle) {
        super(application);	//必须要有
        this.handle = handle;

        if (!handle.contains(key)) {
            load();
        }
    }

    public LiveData<Integer> getNumber() {
        return handle.getLiveData(key);
    }

    void load() {
        SharedPreferences shp = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
        int x = shp.getInt(key, 0);
        handle.set(key, x);
    }

    void save() {
        SharedPreferences shp = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = shp.edit();
        editor.putInt(key, getNumber().getValue());
        editor.apply();
    }

    public void add(int x) {
        handle.set(key, getNumber().getValue() + x);
        //save(); //消耗时间
    }
}

MainActivity:

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
		...;
    }

    @Override
    protected void onPause() {
        super.onPause();
        myViewModel.save();	//每次Activity进入onPause()
    }
}

Navigation

NavHost 容器

Fragement 实现屏幕小块内容,依存于Activity。用栈操作。

NavController 导航切换

NavGraph 图形化导航切换设计

页面切换

创建Fragement。例:HostFragement、DetailFragement

为了方便布局设置,可把FrameLayout改成ConstraintLayout

图形化导航逻辑:New Resource File -> Navigation -> 左上角添加现有Fragement

activity_main.xml添加Containers -> NavHostFragement。

xxxFragement中添加onActivityCreated(@Nullable Bundle saveInstanceState),HostFragement:(点击按钮切换)

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Button button = getView().findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavController controller = Navigation.findNavController(v);
                controller.navigate(R.id.action_homeFragment_to_detailFragment);
            }
        });
    }

DetailFragement:(点击按钮切换)

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getView().findViewById(R.id.button).
                setOnClickListener(Navigation.createNavigateOnClickListener
                                   (R.id.action_detailFragment_to_homeFragment));
    }

MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //导航栏名称改变
        NavController controller = Navigation.findNavController(this, R.id.fragment);
        NavigationUI.setupActionBarWithNavController(this, controller);
    }

    @Override
    public boolean onSupportNavigateUp() {	//导航返回键返回
        NavController controller = Navigation.findNavController(this, R.id.fragment);
        return controller.navigateUp();
        //return super.onSupportNavigateUp();
    }
}

动画

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值