ViewModel

news2024/11/14 20:07:03

1.ViewModel的诞生与作用

Activity

package com.tiger.viewmodel;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    private MyViewModel viewModel;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        viewModel = new ViewModelProvider(this).get(MyViewModel.class);//新版本写法  单例 spring注入

        textView.setText(String.valueOf(viewModel.number));
    }

    public void plusNumber(View view) {
        Log.d("ning",viewModel.toString());
        textView.setText(String.valueOf(++viewModel.number));
    }
}

ViewModel

package com.tiger.viewmodel;

import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {

    public int number;

}

xml 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.397" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.538"
        android:onClick="plusNumber"/>


</androidx.constraintlayout.widget.ConstraintLayout>

解开了之前的疑惑。 

application也是一个context 可以拿到资源文件很多资源。 可以用到上下文的地方可以用它,全局唯一,贯穿整个App运行生命周期。防止内存泄漏

2.LiveData

viewModel+LiveData

viewModel

package com.tiger.livedata;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private MutableLiveData<Integer> currentSecond;

    public MutableLiveData<Integer> getCurrentSecond() {
        if (currentSecond == null){
            currentSecond = new MutableLiveData<>();
            //初始化

            currentSecond.setValue(0);
        }
        return currentSecond;
    }


}

activity

package com.tiger.livedata;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private TextView text;
    private MyViewModel myViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.text);
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        text.setText(String.valueOf(myViewModel.getCurrentSecond().getValue()));

        myViewModel.getCurrentSecond().observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer i) {
                text.setText(String.valueOf(i));

            }
        });


        startTimer();
    }

    private void startTimer() {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                //非UI线程用 postValue
                //ui线程 用setValue
                myViewModel.getCurrentSecond().postValue(myViewModel.getCurrentSecond().getValue()+1);

            }
        },1000,1000);

    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

3.ViewModel + LiveData实现 Fragment 间通信

firstFragment

package com.tiger.livedata2;

import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;


public class FirstFragment extends Fragment {


    private MyViewModel myViewModel;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        Log.d("ning","FirstFragment onCreateView");
        View root = inflater.inflate(R.layout.fragment_first, container, false);
        SeekBar seekBar = root.findViewById(R.id.seekBar);

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

        myViewModel.getProgress().observe(this.getActivity(), new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                seekBar.setProgress(integer,true);
                Log.d("ning",Thread.currentThread().getName());
            }
        });

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                myViewModel.getProgress().setValue(progress);
                Log.d("ning",Thread.currentThread().getName());
            }
//Livedata
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });


        return root;
    }
}

secondFragment

package com.tiger.livedata2;

import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;


public class SecondFragment extends Fragment {

    private MyViewModel myViewModel;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        Log.d("ning","SecondFragment onCreateView");
        View root = inflater.inflate(R.layout.fragment_second, container, false);
        SeekBar seekBar = root.findViewById(R.id.seekBar);

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

        myViewModel.getProgress().observe(this.getActivity(), new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                seekBar.setProgress(integer,true);
            }
        });

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                myViewModel.getProgress().setValue(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });


        return root;
    }

}

viewModel

package com.tiger.livedata2;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {

    private MutableLiveData<Integer>  progress;

    public MutableLiveData<Integer> getProgress() {
        if (progress == null){
            progress = new MutableLiveData<>();
            progress.setValue(0);
        }
        return progress;
    }
}

mainActivity

package com.tiger.livedata2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("ning","MainActivity onCreateView");

        setContentView(R.layout.activity_main);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:max="100"
        android:min="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SecondFragment">

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:max="100"
        android:min="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/fragment"
        android:name="com.tiger.livedata2.FirstFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />

    <fragment
        android:id="@+id/fragment2"
        android:name="com.tiger.livedata2.SecondFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline" />


</androidx.constraintlayout.widget.ConstraintLayout>

4.DataBinding

 

首先会有个坑 ,因为版本问题,重复代码太多,所以加入一个依赖

不加会爆以下错误

Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21) Duplicate class kotlin.internal.jdk7

 

   implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))

build.gradle.kts

plugins {
    id("com.android.application")
}

android {
    namespace = "com.tiger.databinding0"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.tiger.databinding0"
        minSdk = 28
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
//        dataBinding {
//            enable =true
//        }
        buildFeatures { dataBinding = true }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.8.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}

xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="idol"
            type="com.tiger.databinding0.Idol" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.5" />

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="300dip"
            android:layout_height="300dip"
            android:src="@drawable/picture"
            app:layout_constraintBottom_toTopOf="@+id/guideline"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.495"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.454"
            tools:srcCompat="@tools:sample/avatars" />

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="姓名"
            android:text="@{idol.name}"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline"
            app:layout_constraintVertical_bias="0.144" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="76dp"
            tools:text="五星"
            android:text="@{idol.star}"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

idol

package com.tiger.databinding0;

public class Idol {

    public String name;

    public String star;

    public Idol(String name, String star) {
        this.name = name;
        this.star = star;
    }
}

mainActivity

package com.tiger.databinding0;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import android.os.Bundle;

import com.tiger.databinding0.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Idol idol = new Idol("斯嘉丽", "六星");
        activityMainBinding.setIdol(idol);


    }

}

实现Activity与 layout布局的 解耦 

layout绑定它的对象, Activity只需把这个对象set进去。就实现数据绑定了

5.import标签与事件绑定

mainActivity

package com.tiger.databinding0;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import android.os.Bundle;

import com.tiger.databinding0.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Idol idol = new Idol("斯嘉丽", 3);
        activityMainBinding.setIdol(idol);
        activityMainBinding.setEventHandle(new EventHandleListener(this));

    }

}

EventHandleListener

package com.tiger.databinding0;

import android.content.Context;
import android.view.View;
import android.widget.Toast;

public class EventHandleListener {
    private Context context;

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

    public void buttonOnClick(View view){
        Toast.makeText(context,"喜欢",Toast.LENGTH_SHORT).show();
    }

}

StarUtils

package com.tiger.databinding0;

/**
 * @author ningchuanqi
 * @version V1.0
 */
public class StarUtils {

    public static String getStar(int star){
        switch (star){
            case 1:
                return "一星";
            case 2:
                return "二星";
            case 3:
                return "三星";
            case 4:
                return "四星";
            case 5:
                return "五星";
        }
        return "";
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="idol"
            type="com.tiger.databinding0.Idol" />

        <variable
            name="eventHandle"
            type="com.tiger.databinding0.EventHandleListener" />
        <import type="com.tiger.databinding0.StarUtils"/>



    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.5" />

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="300dip"
            android:layout_height="300dip"
            android:src="@drawable/picture"
            app:layout_constraintBottom_toTopOf="@+id/guideline"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.495"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.454"
            tools:srcCompat="@tools:sample/avatars" />

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{idol.name}"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline"
            app:layout_constraintVertical_bias="0.144"
            tools:text="姓名" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="76dp"
            android:text="@{StarUtils.getStar(idol.star)}"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView"
            tools:text="五星" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="喜欢"
            android:onClick="@{eventHandle.buttonOnClick}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline"
            app:layout_constraintVertical_bias="0.694" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

6.二级页面的绑定

通过app: 传参


        <include
            layout="@layout/sub"
            app:idol="@{idol}"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

7.自定义binding加载图片

package com.tiger.databindng3;

import android.graphics.Color;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import androidx.databinding.BindingAdapter;

import com.squareup.picasso.Picasso;

public class ImageViewBindingAdapter {

//    @BindingAdapter("image")//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
//    public static void setImage(ImageView imageView, String url) {
//        Log.d("ning", url);
//        if (!TextUtils.isEmpty(url)) {
//            Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);
//        } else {
//            imageView.setBackgroundColor(Color.GRAY);
//        }
//    }
//
//    //加载本地图片
//    @BindingAdapter("image")//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
//    public static void setImage(ImageView imageView, int resId) {
//        Log.d("ning", "setImageResource");
//        imageView.setImageResource(resId);
//    }

    @BindingAdapter(value = {"image", "defaultImageResource"}, requireAll = false)
//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
    public static void setImage(ImageView imageView, String url, int resId) {
        Log.d("ning", "setImageResource"+url+","+resId);
        if (!TextUtils.isEmpty(url)) {
            Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);
        } else {
            imageView.setImageResource(resId);
        }

    }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="networkImage"
            type="String" />

        <variable
            name="localImage"
            type="int" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">


        <ImageView
            android:id="@+id/imageView"
            android:layout_width="300dip"
            android:layout_height="300dip"
            app:image="@{networkImage}"
            app:defaultImageResource="@{localImage}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/avatars" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
package com.tiger.databindng3;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import android.os.Bundle;

import com.tiger.databindng3.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        activityMainBinding.setNetworkImage("https://copyright.bdstatic.com/vcg/creative/cc9c744cf9f7c864889c563cbdeddce6.jpg@h_1280");
        activityMainBinding.setLocalImage(R.drawable.picture);
    }
}

8.双向绑定

BaseObservable

activity

package com.tiger.databinding4;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import android.os.Bundle;

import com.tiger.databinding4.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        UserViewModel userViewModel = new UserViewModel();
        activityMainBinding.setUserViewModel(userViewModel);
        activityMainBinding.setEvent(new EventHandleListener(userViewModel));
    }
}

 userviewmodel

package com.tiger.databinding4;

import android.util.Log;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class UserViewModel extends BaseObservable {

    private User user;

    public UserViewModel() {
        this.user = new User("Jack");
    }

    @Bindable
    public String getUserName(){
        return user.userName;
    }

    public void  setUserName(String userName){
        if (userName!=null && !userName.equals(user.userName)){
            user.userName = userName;
            Log.d("ning","setUserName:"+userName);
            //当内容发生变化的时候,通知更新页面
            notifyPropertyChanged(BR.userName);
        }

    }


}

User 

package com.tiger.databinding4;

public class User {
    public String userName;

    public User(String userName) {
        this.userName = userName;
    }
}

event 

package com.tiger.databinding4;

import android.view.View;

public class EventHandleListener {

    private UserViewModel userViewModel;

    public EventHandleListener(UserViewModel userViewModel) {
        this.userViewModel = userViewModel;
    }

    public void restore(View view){
        userViewModel.setUserName("请输入内容:");
    }
}

xml 

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="userViewModel"
            type="com.tiger.databinding4.UserViewModel" />
        <variable
            name="event"
            type="com.tiger.databinding4.EventHandleListener" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
<!--双向绑定 @={} -->
        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="@={userViewModel.userName}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="输入框变成 请输入内容"
            android:onClick="@{event.restore}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.497"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/editText"
            app:layout_constraintVertical_bias="0.145" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

ObservableField

activity

package com.tiger.databinding5;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import com.tiger.databinding5.databinding.ActivityMainBinding;


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        activityMainBinding.setUserViewModel(new UserViewModel());
    }
}

user

package com.tiger.databinding5;

/**
 * @author ningchuanqi
 * @version V1.0
 */
public class User {
    public String userName;

    public User(String userName) {
        this.userName = userName;
    }
}

UserViewModel

package com.tiger.databinding5;

import android.util.Log;

import androidx.databinding.ObservableField;

/**
 * @author ningchuanqi
 * @version V1.0
 */
public class UserViewModel {

    private ObservableField<User> userObservableField;

    public UserViewModel(){
        User user = new User("Jack");
        userObservableField = new ObservableField<>();
        userObservableField.set(user);
    }


    public String getUserName(){
        return userObservableField.get().userName;
    }

    public void setUserName(String userName){
        Log.d("ning","userObservableField:"+userName);
        userObservableField.get().userName = userName;
    }

}

xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="userViewModel"
            type="com.tiger.databinding5.UserViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="@={userViewModel.userName}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

9. RecyclerView 的 绑定

activity

package com.tiger.databinding6;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.os.Bundle;

import com.tiger.databinding6.databinding.ActivityMainBinding;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        List<Idol> idols = IdolUtils.get();
        activityMainBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
        RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(idols);

        activityMainBinding.recyclerView.setAdapter(recyclerViewAdapter);
    }
}

RecyclerViewAdapter

package com.tiger.databinding6;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.RecyclerView;

import com.tiger.databinding6.databinding.ItemBinding;

import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {

    List<Idol> idols;

    public RecyclerViewAdapter(List<Idol> idols) {
        this.idols = idols;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //一个binding 对应一个Item
        ItemBinding itemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
        return new MyViewHolder(itemBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Idol idol = idols.get(position);
        holder.itemBinding.setIdol(idol);
    }

    @Override
    public int getItemCount() {
        return idols.size();
    }

    static class MyViewHolder extends RecyclerView.ViewHolder {

        private ItemBinding itemBinding;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
        }

        public MyViewHolder(ItemBinding itemBinding) {
            super(itemBinding.getRoot());
            this.itemBinding = itemBinding;
        }
    }

}

ImageViewBindingAdapter

package com.tiger.databinding6;

import android.graphics.Color;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import androidx.databinding.BindingAdapter;

import com.squareup.picasso.Picasso;

public class ImageViewBindingAdapter {

//    @BindingAdapter("image")//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
//    public static void setImage(ImageView imageView, String url) {
//        Log.d("ning", url);
//        if (!TextUtils.isEmpty(url)) {
//            Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);
//        } else {
//            imageView.setBackgroundColor(Color.GRAY);
//        }
//    }
//
//    //加载本地图片
//    @BindingAdapter("image")//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
//    public static void setImage(ImageView imageView, int resId) {
//        Log.d("ning", "setImageResource");
//        imageView.setImageResource(resId);
//    }

    @BindingAdapter(value = "itemImage", requireAll = false)
//这个image和布局里的 app:image 名字对应  它会把 url传过来  也会把imageView 传过来
    public static void setImage(ImageView imageView, String url) {

        if (!TextUtils.isEmpty(url)) {
            Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);
        } else {
            imageView.setBackgroundColor(Color.GRAY);
        }

    }
}

Idol

package com.tiger.databinding6;

public class Idol {

    public String chName;

    public String enName;

    public String image;

    public Idol(String chName, String enName, String image) {
        this.chName = chName;
        this.enName = enName;
        this.image = image;
    }
}

IdolUtils

package com.tiger.databinding6;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ningchuanqi
 * @version V1.0
 */
public class IdolUtils {
    public static List<Idol> get(){
        List<Idol> list = new ArrayList<>();
        Idol i1 = new Idol("斯嘉丽.约翰逊","Scarlett Johansson","https://5b0988e595225.cdn.sohucs.com/images/20190624/d93dbf866aa2405f8b9b1d660c15db9d.jpeg");
        list.add(i1);

        Idol i2 = new Idol("安吉丽娜·朱莉","Angelina Jolie","https://5b0988e595225.cdn.sohucs.com/images/20190624/0657ccc0066b4e1797ead2b3293230b0.jpeg");
        list.add(i2);

        Idol i3 = new Idol("杰西卡·辛普森","Jessica Simpson","https://5b0988e595225.cdn.sohucs.com/images/20190624/49c95e9b542a4854b2232e67579b9215.jpeg");
        list.add(i3);

        Idol i4 = new Idol("萨尔玛·海耶克","Salma Hayek","https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3893590240,2013198505&fm=26&gp=0.jpg");
        list.add(i4);

        Idol i5 = new Idol("卡门·伊莱克特拉","Carmen Electra","https://5b0988e595225.cdn.sohucs.com/images/20190624/1399d0fda46c467dbd988f2996dccaad.jpeg");
        list.add(i5);

        Idol i6 = new Idol("凯瑟琳·海格尔","Katherine Heigl","https://gimg2.baidu.com/image_search/src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fq_70%2Cc_zoom%2Cw_640%2Fimages%2F20180116%2F74c81a087a28446590734ca257e3eacf.jpeg&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1618118692&t=6c5c1eecb1b0db8664810bfc51f8609b");
        list.add(i6);

        Idol i7 = new Idol("珍妮佛·安妮斯顿","Jennifer Aniston","https://5b0988e595225.cdn.sohucs.com/images/20190624/98e8b18a86004eb79bef58318e93446d.jpeg");
        list.add(i7);

        Idol i8 = new Idol("梅根·福克斯","Megan Fox","https://5b0988e595225.cdn.sohucs.com/images/20190624/37991ee797e6496d99cdee5315082b76.jpeg");
        list.add(i8);

        Idol i9 = new Idol("杰西卡·阿尔芭","Jessica Alba","https://5b0988e595225.cdn.sohucs.com/images/20190624/eb49bf15b9634d579ff89f596c54e0ca.jpeg");
        list.add(i9);

        Idol i10 = new Idol("詹妮弗·洛芙·休伊特","Jennifer Love Hewitt","https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=791729948,2390587761&fm=26&gp=0.jpg");
        list.add(i10);

        return list;
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingVertical="10dip">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="100dip"
            android:layout_height="100dip"
            app:itemImage="@{idol.image}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/guideline2"
            app:layout_constraintHorizontal_bias="0.432"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.054"
            tools:srcCompat="@tools:sample/avatars" />

        <TextView
            android:id="@+id/textViewChName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{idol.chName}"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.138"
            app:layout_constraintStart_toStartOf="@+id/guideline2"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.063"
            tools:text="斯嘉丽.约翰逊" />

        <TextView
            android:id="@+id/textViewEnName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="28dp"
            android:text="@{idol.enName}"
            android:textSize="18sp"
            app:layout_constraintStart_toStartOf="@+id/textViewChName"
            app:layout_constraintTop_toBottomOf="@+id/textViewChName"
            tools:text="Scarlett Johansson" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.4" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <data>
        <variable
            name="idol"
            type="com.tiger.databinding6.Idol" />
    </data>
</layout>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Codeforces Round 929 (Div. 3)- ABCDEFG

A:Turtle Puzzle: Rearrange and Negate 思路&#xff1a; 将负的元素全部排到一起&#xff0c;然后对它们符号取反&#xff0c;然后求所有元素的和&#xff0c;此时就是最大值了。 代码&#xff1a; #include<iostream> using namespace std;void solve() {int n;cin&…

电脑资料管理软件(5个高效批量管理电脑资料的方法)

企业电脑资料管理是企业一大难题&#xff0c;为什么这样说&#xff1f; 首先&#xff0c;企业电脑资料的数量庞大且种类繁多。 其次&#xff0c;电脑资料的安全性和保密性要求高。 再者&#xff0c;电脑资料的管理涉及到多个部门和员工的协作。 ...... 针对此类情况很多企业…

Vue中的组件:构建现代Web应用的基石

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

基于redis实现互斥锁

利用setnx命令实现类似获取锁和释放锁。 获取锁&#xff0c;setnx lock 1&#xff0c;返回值为1视为获取成功&#xff0c;为0视为获取失败 释放锁&#xff0c;del lock 特殊情况&#xff1a; 如果获取锁之后&#xff0c;锁来还来不及释放&#xff0c;redis宕机了&#xff0c;这…

MIT6.5840(6.824)Lab2总结(Raft)

MIT6.5840&#xff08;原MIT6.824&#xff09;Lab2总结&#xff08;Raft&#xff09; 资源分享&#xff1a; 官网地址&#xff1a;http://nil.csail.mit.edu/6.5840/2023/ Raft论文地址&#xff1a;http://nil.csail.mit.edu/6.5840/2023/papers/raft-extended.pdf 官方学生…

gumbel-softmax如何实现离散分布可微+torch代码+原理+证明

文章目录 背景方法通俗理解什么是重参数化gumbel-softmax为什么是gumbeltorch实现思考 背景 这里举一个简单的情况&#xff0c;当前我们有p1, p2, p3三个概率&#xff0c;我们需要得到最优的一个即max(p1, p2, p3)&#xff0c;例如当前p3 max(p1, p2, p3)&#xff0c;那么理想…

SSRF漏洞基础原理(浅层面解释 + 靶场演示)

一、SSRF漏洞的基本概念&#xff1a; SSRF--全名&#xff1a;Server-Side Request Forgery&#xff0c;汉译&#xff1a;服务端请求伪造&#xff0c;漏洞别名“借刀杀人”。 想象以下&#xff0c;现存在一个 Web应用&#xff0c;这个Web应用可以帮助我们能爬取互联网上的其他…

js 添加、删除DOM元素

1. js添加、删除DOM元素 1.1. 添加DOM元素 1.1.1. appendChild()方法 该方法添加的元素位于父元素的末尾&#xff0c;使用方法&#xff1a; parentNode.appenChild(NewNode) // parentNode是需要添加元素的容器&#xff0c;NewNode是新添加的元素   创建一个li元素并添加到…

数据结构与算法-哈希表

引言 在计算机科学中&#xff0c;数据结构与算法是构建高效软件系统的关键基石。其中&#xff0c;哈希表作为一种非常实用的数据结构&#xff0c;以其快速查找、插入和删除等特性&#xff0c;在诸多领域发挥着无可替代的作用。本文将深入探讨哈希表的工作原理、实现细节以及其在…

Qt Creator常见问题解决方法

Qt Creator源文件重命名的正确方法 光改文件名是不够的&#xff0c;还要在.pro文件中的SOURCES中把名字改成之后的。 中文乱码&#xff08;字符集设置&#xff09; 菜单栏-工具-选项-设置为utf-8

Reset Verification IP

Reset Verification IP IP 参数及接口 IP 例化界面 相关函数 assert_reset //置位复位信号 < hierarchy_path>.assert_reset();deassert_reset //取消置位复位信号 < hierarchy_path>.deassert_reset();set_master_mode //设置 RST_VIP 模式为 Master < hi…

STM32基本定时功能

1、定时器就是计数器。 2、怎么计数&#xff1f; 3、我们需要有一恒定频率的方波信号&#xff0c;再加上一个寄存器。 4、比如每来一个上升沿信号&#xff0c;寄存器值加1&#xff0c;就可以完成计数。 5、假设方波频率是100Hz&#xff0c;也就是1秒100个脉冲。…

严刑拷打_微服务

文章详情 &#xff1a;&#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a; 微服务相关知识 ⏱️ 创作时间&#xff1a;2024年03月8日 ———————————————— 文章目…

[数据结构]队列

1.队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为队头 2…

Dynamo3.0.3——六年来最大的更新

Hello大家好&#xff01;我是九哥~ 前几天&#xff0c;Dynamo Core 3.0.0版本发布&#xff0c;迎来了Dynamo六年来最大的一次更新。最大的改变&#xff0c;是更新到了.net8&#xff0c;这回对Dynamo节点包产生不小影响。接下来我们详细看一下都有哪些变化。 首先&#xff0…

【vue.js】文档解读【day 3】 | 列表渲染

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 文章目录 列表渲染v-forv-for 与对象在 v-for 里使用范围值template 上的 v-forv-for与v-if通过key管理状态组件上使用v-for数组变化侦测 列表渲染 v-for 在我们想要渲染出一个数组中的元素时&#xf…

node-day3-es6模块化+webpack

模块化 一、模块化分类 回顾node.js模块化&#xff1a; node.js遵循了CommonJS的模块化规范【见下文】&#xff0c;其中&#xff1a; 1.导入其它模块使用require()方法 2.模块对外共享成员使用module.exports对象 模块化的好处&#xff1a; 大家都遵守同样的模块化规范写代…

Only fullscreen opaque activities can request orientation

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 未经允许不得转载 目录 一、导读二、概览三、分析四、 推荐阅…

【电工学笔记】上册第一、二章

电工学 上次考试败在了单位&#xff0c;这次单位 一定要记熟。 第一章 电源或信号源的电压或电流称为激励,它推动电路工作; 由激励所产生的电压和电流称为响应。 复杂电路中,一般无法事先判断某个支路电流的 实际方向或者某个电路元件电压的实际方向 140V/4算不出总电阻的 …

leetcode26---删除有序数组中的重复项

大家好&#xff0c;我是大唐&#xff0c;刚刷完了几道经典的leetcode题&#xff0c;今天给大家分享一道leetcode上面的快慢指针经典题型---删除有序数组中的重复项&#xff0c;我们往下看。 题目描述 给你一个 非严格递增排列 的数组 nums &#xff0c;请你原地删除重复出现的元…