android JeckPack官方文档学习

1.简介

androidx 命名空间包含 Android Jetpack 库

android.support :版本 28.0.0最后一个版本

Jetpack 库在 androidx 命名空间中发布

1.1 使用:

在项目中使用 androidx 库:

gradle.properties中

android.useAndroidX true

android.enableJetifier true 通过重写其二进制文件来自动迁移现有的第三方库

1.2 在项目中使用Jetpack 库:

settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        jcenter()
    }
}

build.gradle 

dependencies {
    val lifecycle_version = "2.2.0"

    implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
    ...
}

1.3 JetPack库:

activity ads annotation appcompat appsearch arch.core asynclayoutinflater autofill

benchmark biometric browser

car-app camera(*) cardview collection compose compose.animation compose.material  compose.material3 compose.runtime compose.ui

concurrent constrainlayout contentpaper coordinatorlayout core cursoradapter customview databinding datastore

documentfile draganddrop drawerlayout dynamicanimation

emoji emoji2 enterprise exifinterface 

fragment

games glance gridlayout health heifwriter hilt

interpolator

jetifier

leanback legacy lifecycle loader localbroadcastmanager

media media2 media3 mediarouter multidex metrics

navigation

paging palette percentlayout preference print profileinstaller

recylerview remotecallback resourceinspection room

savestate security sharetarget slice slidingpanelayout startup sqlite swiperefreshlayout

test textclassifier

tracing transition tvprovider 

vectordrawable viewpager viewpager2 wear wear.compose wear.tiles wear.watchface webkit window work

material Design

数据绑定(Data Binding)

Lifecycles(关于 activity 以及 fragment 的生命周期)

LiveData(用于更新界面的数据,跟大家之前理解的 model 不一样,它可以感应生命周期)

Navigation(关于 APP 内的导航跳转)

Paging(可以理解为分页加载)

Room(原来有很多第三方的数据库 ormlite 之类的,现在 Google 出手了,这是对 sqlite 数据库的进一步封装)

ViewModel(前面说了 LiveData,而 ViewModel 就是用来管理 LiveData 的,用于连接 view 视图层和 LiveData 数据层,更重要的是它可以感应声明周期)

WorkManager(用于管理后台任务)。

2.Activity

2.1 生命周期:

onCreate

OnStart

onResume

onPause

onStop:

                        应用应释放或调整在应用对用户不可见时的无用资源。

                        例如,应用可以暂停动画效果,或从精确位置更新切换到粗略位置更新。执行 CPU 相对密集的关闭操作

onDestory:应释放先前的回调(例如 onStop())尚未释放的所有资源。

onSaveInstanceState:保存有关 Activity 视图层次结构状态的瞬时信息,例如 EditText 微件中的文本或 ListView 微件的滚动位置。--onCreate中恢复

2.2 Activity的任务栈

使用清单文件

launchMode :standard singleTop singleTask singleInstance

FLAG_ACTIVITY_NEW_TASK(singleTask)

FLAG_ACTIVITY_SINGLE_TOP(singleTop)

FLAG_ACTIVITY_CLEAR_TOP:会销毁位于它之上的所有其他 Activity,并通过 onNewIntent() 将此 intent 传送给它的已恢复实例

taskAffinity:同一应用中的所有 Activity 彼此具有亲和性

FLAG_ACTIVITY_NEW_TASK allowTaskReparenting起作用

2.3 清除返回堆栈

alwaysRetainTaskState(根Activity设置-不会清除)

clearTaskOnLaunch(根Activity设置-会清除)

finishOnTaskLaunch(单个Activity-会清楚,包括根)

public class CameraComponent implements LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void initializeCamera() {
        if (camera == null) {
            getCamera();
        }
    }

}

3.Fragment

3.1 带参数创建fragment

getSupportFragmentManager().beginTransaction()
                .setReorderingAllowed(true)
                .add(R.id.fragment_container_view, ExampleFragment.class, bundle)
                .commit();

--对应
 @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        int someInt = requireArguments().getInt("some_int");
        ...
    }

3.2 FragmentManager

Activity访问:

管理 Fragment 子级的 FragmentManager 的引用 getChildFragmentManager() 

访问其宿主 FragmentManager,可以使用 getParentFragmentManager()。

3.3 任务栈

addToBackStack--popBackStack

如果您在执行移除 Fragment 的事务时未调用 addToBackStack(),则提交事务时会销毁已移除的 Fragment,用户无法返回到该 Fragment。

如果您在移除某个 Fragment 时调用了 addToBackStack(),则该 Fragment 只会 STOPPED,稍后当用户返回时它会 RESUMED

saveBackStack()保存 和 restoreBackStack()弹出

3.4FragmentFactory

FragmentFactory的作用很简单:就是帮助开发者自定义并使用带参数的Fragment构造器。这对于dagger、koin等某些DI框架的使用场景中会非常有帮助

通过注解的方式来管理整个应用中的自定义的Fragment

自定义FragmentFactory
public class MyFragmentFactory extends FragmentFactory {
    private DessertsRepository repository;

    public MyFragmentFactory(DessertsRepository repository) {
        super();
        this.repository = repository;
    }

    @NonNull
    @Override
    public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
        Class fragmentClass = loadFragmentClass(classLoader, className);
        if (fragmentClass == DessertsFragment.class) {
            return new DessertsFragment(repository);//这边newFragment
        } else {
            return super.instantiate(classLoader, className);
        }
    }
}


getSupportFragmentManager().setFragmentFactory(new MyFragmentFactory(repository));


1.注解指定fragment
@TargetFragmentTag("fragment1")

2.使用
mFactory=FragmentFactory.getInstance().init(this, R.id.mContentFl);
mFactory.showFragment(FragmentTag.FRAGMENT1)

3.5动画

setCustomAnimations

3.6Fragment状态

  • INITIALIZED
  • CREATED
  • STARTED
  • RESUMED
  • DESTROYED

3.7Fragment通信

类型

        Activity之间的通信

        Fragment之间的通信

        与子Fragment之间的通信

方法:

         使用ViewModel共享数据

        使用接口共享数据

Fragment自己的toolbar

       onCreate-- setHasOptionsMenu(true);

onCreateOptionsMenu --       inflater.inflate(R.menu.sample_menu, menu);
onOptionsItemSelected--点击事件
onPrepareOptionsMenu--修改菜单
requireActivity().invalidateOptionsMenu()---更新菜单


xml中使用

java中
onViewCreated--viewBinding.myToolbar.inflateMenu
viewBinding.myToolbar.setOnMenuItemClickListener--点击事件
viewBinding.myToolbar.setNavigationIcon(R.drawable.ic_back)--返回
viewBinding.myToolbar.setNavigationOnClickListener

3.8   DialogFragment

         onCreateDialog()onDismiss() onCancel()

3.9 调试fragment

adb shell setprop log.tag.FragmentManager DEBUG
代码捕获:
addOnContextAvailableListener((context) -> {
            if(context.getResources().getBoolean(R.bool.enable_strict_mode)) {
                getSupportFragmentManager().setStrictModePolicy(
                        new FragmentStrictMode.Policy.Builder()
                                .penaltyDeath()
                                .detectFragmentReuse()
                                .allowViolation(FirstFragment.class, FragmentReuseViolation.class)
                                .build()
                );
            }
        }

4.lifeCycle

4.1 android观察者模式

android JeckPack官方文档学习_第1张图片

4.2 lifeCycle主要类

LifecycleOwner:生命周期的拥有者,一般是Activity和Fragment实现这个接口,只有一个方法getLifecycle():Lifecycle
Lifecycle:表示一个生命周期过程对象,可以添加生命周期观察者
Lifecycle.State:生命周期枚举,有DESTROYED、INITIALIZED、CREATED、STARTED、RESUMED
LifecycleRegistry:Lifecycle的子类,对Lifecycle中的抽象方法进行了实现
LifecycleObserver:生命周期观察者,虽是个空接口,但可以通过Lifecycle的注解定义所有的生命周期方法
Lifecycle.Event:生命周期事件,和Activity/Fragment的相应生命周期回调一一对应,有ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP、ON_DESTROY、ON_ANY七种取值,一般和OnLifecycleEvent注解一起使用,用来在LifecycleObserver中标注方法属于哪个生命周期

lifecycle(LifecycleRegistry)相当于被观察者,可以注册,移除通知观察者DefaultLifecycleObserver

-----------------------DefaultLifecycleObserver
class MyLocationListener implements DefaultLifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @Override
    public void onStart(LifecycleOwner owner) {//LifecycleOwner
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @Override
    public void onStop(LifecycleOwner owner) {//LifecycleOwner
        // disconnect if connected
    }
}

------------------------Activity
class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}



---------------------------自定义LifecycleOwner
1、实现LifecycleOwner 接口的方法:getLifecycle()
2、注册Lifecycle new LifecycleRegistry(this)
3、在Activity生命周期函数中分发事件

public class MyActivity extends Activity implements LifecycleOwner {//
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //初始化lifecycleRegistry
        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}

5.ViewModel

android JeckPack官方文档学习_第2张图片

1.数据绑定

以上布局文件名为 activity_main.xml,因此生成的对应类为 ActivityMainBinding

android:paddingLeft-----@BindingAdapter("android:paddingLeft")

可观察的字段

* ObservableBoolean* ObservableByte* ObservableChar* ObservableShort

* ObservableInt* ObservableLong* ObservableFloat* ObservableDouble

* ObservableParcelable

可观察的集合

ObservableArrayMap ObservableArrayList

可观察的对象

BaseObservable

将布局绑定在构架组件

-------------------- activity(ViewModel)

class ViewModelActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

            //把viewModel设置到databinding上
            UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
            binding.viewmodel = userModel;
        }
    }

---------------------ViewModel1
class ScheduleViewModel extends ViewModel {
        LiveData username;

        public ScheduleViewModel() {
            String result = Repository.userName;
            userName = Transformations.map(result, result -> result.value);
        }
    }
---------------------ViewModel2--Observable
class ObservableViewModel extends ViewModel implements Observable {
        private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();

        @Override
        protected void addOnPropertyChangedCallback(
                Observable.OnPropertyChangedCallback callback) {
            callbacks.add(callback);
        }

        @Override
        protected void removeOnPropertyChangedCallback(
                Observable.OnPropertyChangedCallback callback) {
            callbacks.remove(callback);
        }

        void notifyChange() {
            callbacks.notifyCallbacks(this, 0, null);
        }

        void notifyPropertyChanged(int fieldId) {
            callbacks.notifyCallbacks(this, fieldId, null);
        }
    }

---------------------xml



----------------------双向数据绑定@=
 

-----------------实体类
@InverseBindingAdapter("time")
    public static Time getTime(MyView view) {
        return view.getTime();
    }

2.MVVM的概念

View发生改变时,ViewModel会通知Model进行更新数据

Model数据更新后,ViewModel会通知View更新显示

谷歌发布MVVM支持DataBinding:能将数据绑定到xml中

现在谷歌又推出ViewModel和LiveData组件更方便实现MVVM

MVC MVP MVVM的区别

MVC:缺点 Activity 责任过重,Activity充当了V和C,TextView.setTextView()这种逻辑应该放在view

V(SetText)C (Activity中获取数据并显示V上)M(数据)

MVP:MVP把Activity作为view,View并不直接去请求Model,由P去请求

V/A(Activity中通过回调显示V上)P(获取数据)M(数据)

MVVM:省略了findViewbyId,setText的过程

V(xml activity) VM (实体类)M   省略了

6.LiveData

6.1优势

  • UI和实时数据保持一致

因为LiveData采用的是观察者模式,这样一来就可以在数据发生改变时获得通知,更新UI。

  • 不会发生内存泄露

观察者被绑定到组件的生命周期上,当被绑定的组件销毁(onDestroy)时,观察者会立刻自动清理自身的数据。

  • 不会再产生由于Activity处于stop状态而引起的崩溃

例如:当Activity处于后台状态时,是不会收到LiveData的任何事件的。

  • 不需要再解决生命周期带来的问题

LiveData可以感知被绑定的组件的生命周期,只有在活跃状态才会通知数据变化。

  • 实时数据刷新

当组件处于活跃状态或者从不活跃状态到活跃状态时总是能收到最新的数据

  • 解决Configuration Change问题

在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据。

  • 数据共享

如果对应的LiveData是单例的话,就能在app的组件间分享数据。这部分详细的信息可以参考继承LiveData

//----------------------创建LiveData
public class NameViewModel extends ViewModel {

private MutableLiveData currentName;

    public MutableLiveData getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData();
        }
        return currentName;
    }
}
//---------------------观察LiveData(UI发生改变的时候通知)
public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = new ViewModelProvider(this).get(NameViewModel.class);
        final Observer nameObserver = new Observer() {
            @Override
            public void onChanged(@Nullable final String newName) {
                nameTextView.setText(newName);
            }
        };
//观察Livedata
        model.getCurrentName().observe(this, nameObserver);
    }
}
//---------------------更新LiveData,(更新UI)
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});
//LiveData转换
Transformations.map()
Transformations.switchMap()

 6.2数据状态

android JeckPack官方文档学习_第3张图片​​​​​​​

android JeckPack官方文档学习_第4张图片

class SearchManager implements SavedStateRegistry.SavedStateProvider {
    private static String PROVIDER = "search_manager";
    private static String QUERY = "query";
    private String query = null;

    public SearchManager(SavedStateRegistryOwner registryOwner) {
        registryOwner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
            if (event == Lifecycle.Event.ON_CREATE) {
                SavedStateRegistry registry = registryOwner.getSavedStateRegistry();

                // Register this object for future calls to saveState()
                registry.registerSavedStateProvider(PROVIDER, this);

                // Get the previously saved state and restore it
                Bundle state = registry.consumeRestoredStateForKey(PROVIDER);

                // Apply the previously saved state
                if (state != null) {
                    query = state.getString(QUERY);
                }
            }
        });
    }

    @NonNull
    @Override
    public Bundle saveState() {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY, query);
        return bundle;
    }

    ...
}

class SearchFragment extends Fragment {
    private SearchManager searchManager = new SearchManager(this);
    ...
}

7.Work

原理:用来执行后台任务的

优点:

  • 版本兼容性强,向后兼容至API 14。
  • 可以指定约束条件,比如可以选择必须在有网络的条件下执行。
  • 可定时执行也可单次执行。
  • 监听和管理任务状态。
  • 多个任务可使用任务链。
  • 保证任务执行,如当前执行条件不满足或者App进程被杀死,它会等到下次条件满足或者App进程打开后执行。
  • 支持省电模式。

替换:

WorkManager API 是一个适合用来替换先前的 Android 后台调度 API(包括 FirebaseJobDispatcher、GcmNetworkManager  和 JobScheduler)的推荐组件。

应用:

  • 向后端服务发送日志或分析数据。
  • 定期将应用数据与服务器同步。

AS中引用build.gradle

dependencies {
    def work_version = "2.7.1"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"

    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"

    // optional - RxJava2 support
    implementation "androidx.work:work-rxjava2:$work_version"

    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"

    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"

    // optional - Multiprocess support
    implementation "androidx.work:work-multiprocess:$work_version"
}

WorkManager 可处理三种类型的永久性工作:

  • 立即执行:必须立即开始且很快就完成的任务,可以加急。
  • 长时间运行:运行时间可能较长(有可能超过 10 分钟)的任务。
  • 可延期执行:延期开始并且可以定期运行的预定任务。
类型 周期 使用方式
立即 一次性 OneTimeWorkRequest 和 Worker

如需处理加急工作- 调用 setExpedited()

长期运行 一次性或定期

任意 WorkRequest 或 Worker

在工作器中调用 setForeground() 来处理通知

可延期 一次性或定期 PeriodicWorkRequest 和 Worker

基础使用:

1.定义worker ,实现dowork

public class UploadWorker extends Worker {

2.利用建造者创建workRequest

WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(UploadWorker.class)
       .build();

3.将 WorkRequest 提交给系统

WorkManager
    .getInstance(myContext)
    .enqueue(uploadWorkRequest);

具体用法:

常见的Worker

1.自动运行在后台线程的Worker

2.结合协程的CoroutineWorker

​​​​​​​3.结合RxJava2RxWorker和以上三个类的基类的ListenableWorker

4.RemoteListenableWorker和RemoteCoroutineWorker

从 WorkManager 2.6 开始,借助 RemoteListenableWorker 或者 RemoteCoroutineWorker可以将任务运行在任意指定进程,实现跨进程的监听

//------------------------work用法(中间进度)

public class ProgressWorker extends Worker {

    private static final String PROGRESS = "PROGRESS";
    private static final long DELAY = 1000L;

    public ProgressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters parameters) {
        super(context, parameters);
        // Set initial progress to 0
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 0).build());
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            Thread.sleep(DELAY);
        } catch (InterruptedException exception) {
      
        }
        // Set progress to 100 after you are done doing your work.
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 100).build());
        return Result.success();
    }
}

创建workRequest

  • //--------------------一次性任务
    WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);
    
    //-----------------------加急任务
    OneTimeWorkRequest request = new OneTimeWorkRequestBuilder()
        .setInputData(inputData)
        .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
        //加急工作
        .build();
    //-----------------------延迟任务
    WorkRequest myWorkRequest =
          new OneTimeWorkRequest.Builder(MyWork.class)
                   .setInitialDelay(10, TimeUnit.MINUTES)
                   .build();
    -------------------------重试任务
    WorkRequest myWorkRequest =
           new OneTimeWorkRequest.Builder(MyWork.class)
                   .setBackoffCriteria(
                           BackoffPolicy.LINEAR,//重试间隔都会增加约 10 秒
                           OneTimeWorkRequest.MIN_BACKOFF_MILLIS,//此值不能超过 10 秒
                           TimeUnit.MILLISECONDS)
                   .build();
    
    // ------------------------构建约束条件
    约束条件(NetworkType BatteryNotLow RequiresCharging DeviceIdle StorageNotLow)
            val constraints = Constraints.Builder()
                .setRequiresBatteryNotLow(true) // 非电池低电量
                .setRequiredNetworkType(NetworkType.CONNECTED) // 网络连接的情况
                .setRequiresStorageNotLow(true) // 存储空间足
                .build()
    
            // 储存照片
            val save = OneTimeWorkRequestBuilder()
                .setConstraints(constraints)
                .addTag(TAG_OUTPUT)
                .build()
            continuation = continuation.then(save)
    //-------------------------标记---tag
    WorkRequest myWorkRequest =
           new OneTimeWorkRequest.Builder(MyWork.class)
           .addTag("cleanup")
           .build();
    
    //-----------------------data
    WorkRequest myUploadWork =
          new OneTimeWorkRequest.Builder(UploadWork.class)
               .setInputData(
                   new Data.Builder()
                       .putString("IMAGE_URI", "http://...")
                       .build()
               )
               .build();
    
    //-------协程--getForegroundInfo可让 WorkManager 在您调用 setExpedited() 时显示通知。
    class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
       CoroutineWorker(appContext, workerParams) {
    
       override suspend fun getForegroundInfo(): ForegroundInfo {
           return ForegroundInfo(
               NOTIFICATION_ID, createNotification()
           )
       }
    
       override suspend fun doWork(): Result {
           TODO()
       }
    
        private fun createNotification() : Notification {
           TODO()
        }
    
    }
    
    //----------------------定期任务
    PeriodicWorkRequest saveRequest =
           new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
               // Constraints
               .build();
    //-----------------------定时任务,每小时的15分钟执行的任务
    WorkRequest saveRequest =
           new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
                   1, TimeUnit.HOURS,
                   15, TimeUnit.MINUTES)
               .build();
    
    
    

WorkManager使用

//---------------------多任务执行(连接)
workManager.beginWith(
            mutableListOf(
                OneTimeWorkRequest.from(CleanUpWorker::class.java)
            ))
            .then(OneTimeWorkRequestBuilder().setInputData(createInputDataForUri()).build())
            .then(OneTimeWorkRequestBuilder().build())
            .enqueue()

// -----------------------多任务按顺序执行
workManager.beginUniqueWork(//beginUniqueWork
            IMAGE_MANIPULATION_WORK_NAME, // 任务名称
            ExistingWorkPolicy.REPLACE, // 任务相同的执行策略 分为REPLACE,KEEP,APPEND
            mutableListOf(
                OneTimeWorkRequest.from(CleanUpWorker::class.java) 
            ))
            .then(OneTimeWorkRequestBuilder().setInputData(createInputDataForUri()).build())
            .then(OneTimeWorkRequestBuilder().build())
            .enqueue()

//-------------------------唯一工作执行
PeriodicWorkRequest sendLogsWorkRequest = new
      PeriodicWorkRequest.Builder(SendLogsWorker.class, 24, TimeUnit.HOURS)
              .setConstraints(new Constraints.Builder()
              .setRequiresCharging(true)
          .build()
      )
     .build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(//唯一
     "sendLogs",
     ExistingPeriodicWorkPolicy.KEEP,
     sendLogsWorkRequest);
//---------------------合并器,父输出传入子输入
OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class)
       .setInputMerger(ArrayCreatingInputMerger.class)
       .setConstraints(constraints)
       .build();

//----------------------------取消任务
// by id
workManager.cancelWorkById(syncWorker.id);

// by name
workManager.cancelUniqueWork("sync");

// by tag
workManager.cancelAllWorkByTag("syncTag");

//--------------------------复杂工作查询Workquery,从上面tag中查找,检测状态

workManager.getWorkInfoByIdLiveData(syncWorker.id)
        .observe(getViewLifecycleOwner(), workInfo -> {
    if (workInfo.getState() != null &&
            workInfo.getState() == WorkInfo.State.SUCCEEDED) {
        Snackbar.make(requireView(),
                    R.string.work_completed, Snackbar.LENGTH_SHORT)
                .show();
   }
});

WorkQuery workQuery = WorkQuery.Builder
       .fromTags(Arrays.asList("syncTag"))
       .addStates(Arrays.asList(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
       .addUniqueWorkNames(Arrays.asList("preProcess", "sync")
     )
    .build();

ListenableFuture> workInfos = workManager.getWorkInfos(workQuery);

//--------------------------------观察进度
WorkManager.getInstance(getApplicationContext())
     // requestId is the WorkRequest id
     .getWorkInfoByIdLiveData(requestId)
     .observe(lifecycleOwner, new Observer() {
             @Override
             public void onChanged(@Nullable WorkInfo workInfo) {
                 if (workInfo != null) {
                     Data progress = workInfo.getProgress();
                     int value = progress.getInt(PROGRESS, 0)
                     // Do something with progress
             }
      }
});

调试:

public class MyApplication extends Application implements Configuration.Provider {
    @NonNull
    @Override
    public Configuration getWorkManagerConfiguration() {
        return new Configuration.Builder()
                .setMinimumLoggingLevel(android.util.Log.DEBUG)
                .build();
    }
}

adb shell dumpsys jobscheduler

adb shell am broadcast -a "androidx.work.diagnostics.REQUEST_DIAGNOSTICS" -p ""
 

协程:

  • 处理多任务并发的手段,最大的特点就是可以自动帮助我们切换线程​​​​​​​
  • 协程就像轻量级的线程。线程由系统调度,协程由开发者控制。
  • kotlin协程本质上是对线程池的封装
 GlobalScope.launch {
    withContext(Dispatchers.Main){
               //切换线程
            }
  }
//主线程协程
GlobalScope.launch(Dispatchers.Main) {}
lifecycleScope.launch {}
viewModelScope.launch {}

//默认情况下协程是串行的

//并行方式
lifecycleScope.launch {
      lifecycleScope.async { getDataA() }
      lifecycleScope.async { getDataB() }     
}
//协程停止
?.cancel()
lifecycleScope和viewModelScope会绑定调用者的生命周期,因此通常情况下不需要手动去停止

添加依赖:

implementation'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'

implementation'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'

​​​​​​​​​​​​​​8.Room

8.1示例

------------------------Entity-----------------------------
@Entity
public class User {
    @PrimaryKey
    public int uid;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
}
------------------------Dao-----------------------------
@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}
------------------------Database-----------------------------
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

UserDao userDao = db.userDao();
List users = userDao.getAll();

8.2

​​​​​​​
javaCompileOptions {
    annotationProcessorOptions {
        arguments = ["room.schemaLocation":
                             "$projectDir/schemas".toString()]
    }
}

配置如上可以看到json文件

8.3 调试数据库

adb shell
sqlite3 /data/data/your-app-package/databases/XXX.db

.help 帮助

.exit  退出

.table 查看表

select * from  "具体表名"; 注意分隔 查询所有字段

排序 order by:

select * from  "具体表名" order by XXX;排序

select * from  "具体表名" order by XXX desc;逆序

条件查询 where:

select * from "表名" where "字段名"='字段值';

select * from "表名" where "字段名" between "" and  "";

select * from "表名" where "字段名" not between "" and  "";

select * from "表名" where "字段名" is NULL;空查询

多条件查询 or ,and,in, not in:

select * from "表名" where "字段条件语句1"  and "字段条件语句2" or "字段条件语句3";

select * from "表名" where "字段名" in "字段值1,字段值2" ;

select * from "表名" where "字段名" not  in "字段值1,字段值2" ;

模糊查询 like:

select * from "表名" where "字段名"  like "字段值";

通配符:_ 代表一个未指定字符,% 代表不定个未指定字符

select * from "表名" where "字段名"  like " _";以_表示未知字符

select * from "表名" where "字段名" like '[ALN]%'以A或L或N开头的

更新:

update ‘表名’ set value='字段值' where ‘字段名’='字段值';

多表查询:

select "表别名.字段名" from "表名A" A left join "表名B" B ON A.Key = B.key

select "字段名" from "表名A" A left join "表名B" B ON A.Key = B.key Where B.key is null

select "字段名" from "表名A" A inner join "表名B" B ON A.Key = B.key

select "字段名" from "表名A" A right join "表名B" B ON A.Key = B.key

select "字段名" from "表名A" A right join "表名B" B ON A.Key = B.key Where A.key is null

​​​​​​​select "字段名" from "表名A" A full outer join "表名B" B ON A.Key = B.key

​​​​​​​select "字段名" from "表名A" A full outer join "表名B" B ON A.Key = B.key Where A.key is null or B.key is null

android JeckPack官方文档学习_第5张图片​​​​​​​​​​​​​​

 

参考:即学即用Android Jetpack - WorkManger - 简书

LiveData 概览  |  Android 开发者  |  Android Developers

https://blog.csdn.net/m0_37700275/article/details/104683011

你可能感兴趣的:(学习JectPack,android,webview,tv)