Android一些基础-04-事件和Fragment

事件

Android 框架中管理一个事件队列,当有事件发生时,事件就被放入到队列中。

事件会被传递到屏幕上触摸发生位置所对应的视图。除了事件通知外,该视图还会接收到一系列(取决于事件类型)关于事件性质的信息,例如用户指尖与屏幕接触点的坐标。

视图处理被传递事件,必须有事件监听器。所有用户界面组件皆派生自 Android 的 View 类,该类包含一系列事件监听器接口,每个接口都包含一个回调方法的抽象声明。

去响应一个特定类型的事件,视图必须注册合适的事件监听着,并且实现对应的回调方法。

事件监听器和回调方法

onClickListener:探测用户点击哪里然后松开,配合 onClick 方法使用,该方法会接收一个对接收事件的视图的引用作为参数。

onLongClickListener:检测用户长按一个视图一段时间,配合 onLongClick() 方法使用。

onTouchListener:检测任何形式与屏幕的接触,包括单点、多点和各种手势,配合 onTouch() 方法。

onCreateContextMenuListener:监听长按创建上下文菜单,配合 onCreateContextMenu() 方法使用,该方法传递一个菜单,这个视图接收一个事件和一个菜单对象。

onFocusChangeListener:检测当因与轨迹球或导航键交互而导致焦点从当前视图移开的情况。配合方法 onFocusChange() 。

onKeyListener:用于检测在某个视图获得焦点时,设备上的某个按键何时被按下。配合方法 onKey() 使用。

什么是 Fragment

Fragment 是应用程序用户界面中一个独立的、模块化的部分,以及与之对应的行为,它可以嵌入到 Activity 中。 在应用程序设计阶段,Fragment 可组合起来创建一个 Activity;而在应用程序运行时,Fragment 可添加到 Activity 中或从 Activity 中移除,以创建动态 Activity 中移除,以创建动态变化的用户界面。

Fragment 只能作为 Activity 的一部分使用,不能作为独立的应用程序元素实例化。 Fragment 可以被认为是一个功能性的" 子 Activity ",其生命周期与完整 Activity 的生命周期相似。

在 Fragment 中使用 ConstraintLayout 需要在 layout_width 和 height 前加 android 前缀,android:layout_width="match_parent"

如果在 Activity 的Xml文件中引入 Fragment 需要继承 FragmentActivity,默认AppCompatActivity即可,因为是这样的继承关系

java 复制代码
package com.example.basepractice;  
  
import android.os.Bundle;  
import android.os.PersistableBundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.TextView;  
  
import androidx.activity.EdgeToEdge;  
import androidx.annotation.NonNull;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.constraintlayout.widget.ConstraintSet;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
import androidx.fragment.app.FragmentActivity;  
  
import com.example.basepractice.databinding.ActivityMainBinding;  
  
public class MainActivity extends FragmentActivity {  
    public ActivityMainBinding binding;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  
        binding = ActivityMainBinding.inflate(getLayoutInflater());  
        View view = binding.getRoot();  
        setContentView(view);  
        ConstraintSet set = new ConstraintSet();  

  
    }  
  
}
html 复制代码
<?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:id="@+id/main"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".MainActivity">  
  
    <androidx.fragment.app.FragmentContainerView  
        android:id="@+id/fragment1"  
        android:name="com.example.basepractice.DemoFragment"  
        android:layout_width="0dp"  
        android:layout_height="wrap_content"  
        app:layout_constraintTop_toTopOf="parent"  
        app:layout_constraintBottom_toTopOf="@id/button8"  
        app:layout_constraintEnd_toEndOf="@id/button12"  
        app:layout_constraintStart_toStartOf="@id/button11"  
        >  
  
    </androidx.fragment.app.FragmentContainerView>  
  
    <Button  
        android:id="@+id/button8"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Button"  
        app:layout_constraintBottom_toBottomOf="parent"  
        app:layout_constraintEnd_toStartOf="@+id/button12"  
        app:layout_constraintHorizontal_chainStyle="spread_inside"  
        app:layout_constraintStart_toEndOf="@+id/button11"  
        app:layout_constraintTop_toTopOf="parent" />  
  
    <Button  
        android:id="@+id/button11"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Button"  
        app:layout_constraintBaseline_toBaselineOf="@+id/button8"  
        app:layout_constraintEnd_toStartOf="@+id/button8"  
        app:layout_constraintStart_toStartOf="parent" />  
  
    <Button  
        android:id="@+id/button12"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Button"  
        app:layout_constraintBaseline_toBaselineOf="@+id/button8"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintStart_toEndOf="@+id/button8" />  
  
</androidx.constraintlayout.widget.ConstraintLayout>

如果希望 Fragment 的尺寸通过 Activity 来设置,则需要把想指定的尺寸设置为 0dp

xml 复制代码
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    tools:context=".MainActivity"  
    >  
  
    <Button  
        android:id="@+id/button"  
        android:layout_width="0dp"  
        android:layout_height="wrap_content"  
        android:text="这是个Fragment的按钮"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintStart_toStartOf="parent"  
        app:layout_constraintTop_toTopOf="parent" />  
</androidx.constraintlayout.widget.ConstraintLayout>

把 Fragment 放入Activity Java 代码中进行管理有这些步骤

1、创建一个 Fragment 类的实例

2、传递任何额外的 Intent 参数到这个实例中

3、持有一个 Fragment Manager 的实例

4、在 Fragment Manager 实例上调用 beginTransaction() 方法,返回一个 fragment transaction 实例。

5、在 fragment transaction 实例上调用 add() 方法,将用于容纳该 Fragment 的视图的资源 ID 和片段类实例作为参数传入.

6、调用 ragment transaction 的 commit() 方法。

这6步转为代码可简化至这种形态

java 复制代码
DemoFragment demoFragment = new DemoFragment();  
getSupportFragmentManager().beginTransaction()  
        .add(R.id.fragment1, demoFragment)  
        .commitNow();

图形界面添加 Fragment 到 Activity 可以通过拖拽这个 FragmentContainerView

Activity 与 Fragment 的数据传递

Fragment 把数据传递给 Activity

Fragment 中:

1、定义接口和接口方法

2、声明接口类型对象

3、在 onAttach 方法中进行接口类型对象实例化

4、在某个方法中调用接口方法

代码如下

java 复制代码
package com.example.basepractice;  
  
import android.content.Context;  
import android.os.Bundle;  
  
import androidx.annotation.NonNull;  
import androidx.fragment.app.Fragment;  
  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.Button;  
  
/**  
 * A simple {@link Fragment} subclass.  
 * Use the {@link DemoFragment#newInstance} factory method to  
 * create an instance of this fragment. */public class DemoFragment extends Fragment {  
    // 第一步:定义接口  
    public interface OnFragmentInteractionListener {  
        // TODO: Update argument type and name  
        void onDataFromFragment(String str);  
    }  
    // 第二步:定义接口变量  
    private OnFragmentInteractionListener mListener;  
  
    // TODO: Rename parameter arguments, choose names that match  
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER  
    private static final String ARG_PARAM1 = "param1";  
    private static final String ARG_PARAM2 = "param2";  
  
    // TODO: Rename and change types of parameters  
    private String mParam1;  
    private String mParam2;  
  
    private Button button;  
  
    public DemoFragment() {  
        // Required empty public constructor  
    }  
  
    // 第三步:实例化mListener  
    @Override  
    public void onAttach(@NonNull Context context) {  
        super.onAttach(context);  
        if (context instanceof OnFragmentInteractionListener) {  
            mListener = (OnFragmentInteractionListener) context;  
        } else {  
            throw new RuntimeException(context.toString()  
                    + " must implement OnFragmentInteractionListener");  
        }  
    }  
  
    // 第四步:调用接口方法  
    public void buttonClick() {  
        String str = "Hello from Fragment";  
        mListener.onDataFromFragment(str);  
    }  
  
    /**  
     * Use this factory method to create a new instance of     * this fragment using the provided parameters.     *     * @param param1 Parameter 1.  
     * @param param2 Parameter 2.  
     * @return A new instance of fragment DemoFragment.  
     */    // TODO: Rename and change types and number of parameters  
    public static DemoFragment newInstance(String param1, String param2) {  
        DemoFragment fragment = new DemoFragment();  
        Bundle args = new Bundle();  
        args.putString(ARG_PARAM1, param1);  
        args.putString(ARG_PARAM2, param2);  
        fragment.setArguments(args);  
        return fragment;  
    }  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        if (getArguments() != null) {  
            mParam1 = getArguments().getString(ARG_PARAM1);  
            mParam2 = getArguments().getString(ARG_PARAM2);  
        }  
  
    }  
  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                             Bundle savedInstanceState) {  
        // 加载片段布局  
        View rootView = inflater.inflate(R.layout.fragment_demo, container, false);  
  
        button = rootView.findViewById(R.id.button);  
        button.setOnClickListener(new Button.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
//                buttonClick();  
            }  
        });  
        // Inflate the layout for this fragment  
        return rootView;  
    }  
  
  
}

Activity 中:

1、创建 Fragment 实例

2、实现 Fragment 的接口方法

3、通过 Fragment 实例调用实例方法,这个实例方法中会调用 Fragment 的接口方法

代码如下

java 复制代码
package com.example.basepractice;  
  
import android.os.Bundle;  
import android.os.PersistableBundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.TextView;  
  
import androidx.activity.EdgeToEdge;  
import androidx.annotation.NonNull;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.constraintlayout.widget.ConstraintSet;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
import androidx.fragment.app.FragmentActivity;  
import androidx.fragment.app.FragmentManager;  
import androidx.fragment.app.FragmentTransaction;  
  
import com.example.basepractice.databinding.ActivityMainBinding;  
  
public class MainActivity extends FragmentActivity implements DemoFragment.OnFragmentInteractionListener {  
    public ActivityMainBinding binding;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  
        binding = ActivityMainBinding.inflate(getLayoutInflater());  
        View view = binding.getRoot();  
        setContentView(view);  
  
        // 第一步:获取fragment实例  
        DemoFragment demoFragment = new DemoFragment();  
        getSupportFragmentManager().beginTransaction()  
                .add(R.id.fragment1, demoFragment)  
                .commitNow();  
  
        // 第三步:调用接口方法  
        demoFragment.buttonClick();  
  
    }  
  
    // 第二步:实现接口方法  
    @Override  
    public void onDataFromFragment(String str) {  
        Log.i("TAG", "onDataFromFragment: " + str);  
    }  
}

Activity 把数据传递给 Fragment

以下这种方法也适用于 xml 文件中包含 Fragment 的情况

1、在 Fragment 中定义公开的接收方法

2、在 Activity 中通过 Fragment 实例调用这个公开的方法传值

代码如下

java 复制代码
package com.example.basepractice;  
  
import android.content.Context;  
import android.os.Bundle;  
  
import androidx.annotation.NonNull;  
import androidx.fragment.app.Fragment;  
  
import android.util.Log;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.Button;  
  
/**  
 * A simple {@link Fragment} subclass.  
 * Use the {@link DemoFragment#newInstance} factory method to  
 * create an instance of this fragment. */public class DemoFragment extends Fragment {  
    // 第一步:定义接口  
    public interface OnFragmentInteractionListener {  
        // TODO: Update argument type and name  
        void onDataFromFragment(String str);  
    }  
    // 第二步:定义接口变量  
    private OnFragmentInteractionListener mListener;  
  
    // TODO: Rename parameter arguments, choose names that match  
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER  
    private static final String ARG_PARAM1 = "param1";  
    private static final String ARG_PARAM2 = "param2";  
  
    // TODO: Rename and change types of parameters  
    private String mParam1;  
    private String mParam2;  
  
    private Button button;  
  
    public DemoFragment() {  
        // Required empty public constructor  
    }  
  
    // 第三步:实例化mListener  
    @Override  
    public void onAttach(@NonNull Context context) {  
        super.onAttach(context);  
        if (context instanceof OnFragmentInteractionListener) {  
            mListener = (OnFragmentInteractionListener) context;  
        } else {  
            throw new RuntimeException(context.toString()  
                    + " must implement OnFragmentInteractionListener");  
        }  
    }  
  
    // 第四步:调用接口方法  
    public void buttonClick() {  
        String str = "Hello from Fragment";  
        mListener.onDataFromFragment(str);  
    }  
  
    /**  
     * Use this factory method to create a new instance of     * this fragment using the provided parameters.     *     * @param param1 Parameter 1.  
     * @param param2 Parameter 2.  
     * @return A new instance of fragment DemoFragment.  
     */    // TODO: Rename and change types and number of parameters  
    public static DemoFragment newInstance(String param1, String param2) {  
        DemoFragment fragment = new DemoFragment();  
        Bundle args = new Bundle();  
        args.putString(ARG_PARAM1, param1);  
        args.putString(ARG_PARAM2, param2);  
        fragment.setArguments(args);  
        return fragment;  
    }  
  
    // 用于接收来自Activity的数据  
    public void receiveDataFromActivity(String message) {  
        Log.i("fragment", "receiveDataFromActivity: " + message);  
    }  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        if (getArguments() == null) {  
            Log.i("demoFragment", "onCreate: Arguments are null");  
        }  
//        mParam1 = getArguments().getString(ARG_PARAM1);  
//        mParam2 = getArguments().getString(ARG_PARAM2);  
//        String message = getArguments().getString("message");  
//        Log.i("fragment", "onCreate: " + message);  
  
  
    }  
  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                             Bundle savedInstanceState) {  
        // 加载片段布局  
        View rootView = inflater.inflate(R.layout.fragment_demo, container, false);  
  
        button = rootView.findViewById(R.id.button);  
        button.setOnClickListener(new Button.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
//                buttonClick();  
            }  
        });  
  
        if (getArguments() == null) {  
            Log.i("demoFragment", "onCreate: Arguments are null");  
        }  
        // Inflate the layout for this fragment  
        return rootView;  
    }  
  
  
}
java 复制代码
package com.example.basepractice;  
  
import android.os.Bundle;  
import android.os.PersistableBundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.TextView;  
  
import androidx.activity.EdgeToEdge;  
import androidx.annotation.NonNull;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.constraintlayout.widget.ConstraintSet;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
import androidx.fragment.app.FragmentActivity;  
import androidx.fragment.app.FragmentManager;  
import androidx.fragment.app.FragmentTransaction;  
  
import com.example.basepractice.databinding.ActivityMainBinding;  
  
public class MainActivity extends FragmentActivity implements DemoFragment.OnFragmentInteractionListener {  
    public ActivityMainBinding binding;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  
        binding = ActivityMainBinding.inflate(getLayoutInflater());  
        View view = binding.getRoot();  
        setContentView(view);  
  
        FragmentManager fragmentManager = getSupportFragmentManager();  
        DemoFragment demoFragment = (DemoFragment) fragmentManager.findFragmentById(R.id.fragment1);  
  
        if (demoFragment == null) {  
            Log.i("Tag", "onCreate: 空");  
        } else {  
            // 传递数据给fragment  
            demoFragment.receiveDataFromActivity("Activity 的数据");  
        }  
  
    }  
  
    void fragmentData2Activity() {  
        // 第一步:获取fragment实例  
        DemoFragment demoFragment = new DemoFragment();  
        getSupportFragmentManager().beginTransaction()  
                .add(R.id.fragment1, demoFragment)  
                .commitNow();  
  
        // 第三步:调用接口方法  
        demoFragment.buttonClick();  
    }  
  
    // 第二步:实现接口方法  
    @Override  
    public void onDataFromFragment(String str) {  
        Log.i("TAG", "onDataFromFragment: " + str);  
    }  
}

ViewModel 方式 Activity 与 Fragment 的数据传递

先安装依赖

arduino 复制代码
dependencies {  
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7'  
}

定义 ViewModel , 注意这里的 getter 和 setter 不是传统的 getter 和 setter ,这种是经过 MutableLiveData 检测可避免一些问题

Java 复制代码
package com.example.basepractice;  
  
import androidx.lifecycle.MutableLiveData;  
import androidx.lifecycle.ViewModel;  
  
public class DataViewModel extends ViewModel {  
    private MutableLiveData<String> shareData = new MutableLiveData<>();  
  
    public MutableLiveData<String> getData() {  
        return shareData;  
    }  
  
    public void setData(String data) {  
        shareData.setValue(data);  
    }  
}

Activity 中

Java 复制代码
package com.example.basepractice;  
  
import android.os.Bundle;  
import android.os.PersistableBundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.TextView;  
  
import androidx.activity.EdgeToEdge;  
import androidx.annotation.NonNull;  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.constraintlayout.widget.ConstraintSet;  
import androidx.core.graphics.Insets;  
import androidx.core.view.ViewCompat;  
import androidx.core.view.WindowInsetsCompat;  
import androidx.fragment.app.FragmentActivity;  
import androidx.fragment.app.FragmentManager;  
import androidx.fragment.app.FragmentTransaction;  
import androidx.lifecycle.ViewModelProvider;  
  
import com.example.basepractice.databinding.ActivityMainBinding;  
  
public class MainActivity extends FragmentActivity implements DemoFragment.OnFragmentInteractionListener {  
    public ActivityMainBinding binding;  
    private DataViewModel dataViewModel;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  
        dataViewModel = new ViewModelProvider(this).get(DataViewModel.class);  
        dataViewModel.setData("来自Activity的数据");  
  
    }  
  

}

Fragment 中

Java 复制代码
package com.example.basepractice;  
  
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.TextView;  
  
/**  
 * A simple {@link Fragment} subclass.  
 * Use the {@link ViewModelFragment#newInstance} factory method to  
 * create an instance of this fragment. */public class ViewModelFragment extends Fragment {  
  
    // TODO: Rename parameter arguments, choose names that match  
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER  
    private static final String ARG_PARAM1 = "param1";  
    private static final String ARG_PARAM2 = "param2";  
  
    // TODO: Rename and change types of parameters  
    private String mParam1;  
    private String mParam2;  
    private TextView textView;  
  
    private DataViewModel dataViewModel;  
  
    public ViewModelFragment() {  
        // Required empty public constructor  
    }  
  
    /**  
     * Use this factory method to create a new instance of     * this fragment using the provided parameters.     *     * @param param1 Parameter 1.  
     * @param param2 Parameter 2.  
     * @return A new instance of fragment ViewModelFragment.  
     */    // TODO: Rename and change types and number of parameters  
    public static ViewModelFragment newInstance(String param1, String param2) {  
        ViewModelFragment fragment = new ViewModelFragment();  
        Bundle args = new Bundle();  
        args.putString(ARG_PARAM1, param1);  
        args.putString(ARG_PARAM2, param2);  
        fragment.setArguments(args);  
        return fragment;  
    }  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        if (getArguments() != null) {  
            mParam1 = getArguments().getString(ARG_PARAM1);  
            mParam2 = getArguments().getString(ARG_PARAM2);  
        }  
    }  
  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                             Bundle savedInstanceState) {  
        // 加载片段布局  
        View rootView = inflater.inflate(R.layout.fragment_view_model, container, false);  
        textView = rootView.findViewById(R.id.textView);  
  
        dataViewModel = new ViewModelProvider(requireActivity()).get(DataViewModel.class);  
        dataViewModel.getData().observe(getViewLifecycleOwner(), new Observer<String>() {  
            @Override  
            public void onChanged(String s) {  
                textView.setText(s);  
                Log.i("ViewModelFragment", "onChanged: " + s);  
            }  
        });  
        // Inflate the layout for this fragment  
        return rootView;  
    }  
}
html 复制代码
<?xml version="1.0" encoding="utf-8"?>  
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    tools:context=".MainActivity">  
    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="40dp"  
        android:textSize="20sp"  
        app:layout_constraintTop_toTopOf="parent"  
        app:layout_constraintStart_toStartOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        android:id="@+id/textView"  
        >  
  
    </TextView>  
  
</androidx.constraintlayout.widget.ConstraintLayout>

运行效果

相关推荐
每次的天空1 小时前
Android第十一次面试flutter篇
android·flutter·面试
renxhui3 小时前
Android 性能优化(四):卡顿优化
android·性能优化
二流小码农3 小时前
鸿蒙开发:UI界面分析利器ArkUI Inspector
android·ios·harmonyos
CYRUS_STUDIO4 小时前
FART 精准脱壳:通过配置文件控制脱壳节奏与范围
android·安全·逆向
小疯仔4 小时前
使用el-input数字校验,输入汉字之后校验取消不掉
android·开发语言·javascript
墨狂之逸才4 小时前
Data Binding Conversion 详解
android
iceBin5 小时前
uniapp打包安卓App热更新,及提示下载安装
android·前端
杨充5 小时前
高性能图片优化方案
android
墨狂之逸才5 小时前
BindingAdapter名称的对应关系、命名规则和参数定义原理
android
hellokai5 小时前
ReactNative介绍及简化版原理实现
android·react native