Android的基础开发

基础开发

listView

ListView就是列表条目,可以向下滚动,也可以点击。

首先设置两个视图布局

activity_main2.xml【充当容器{ListView}】

<ListViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/lv"/>
list_view_item.xml【充当容器中的组件{TextView}】<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tv1"android:textSize="30sp"/>

设置主方法

private List<ListViewBean> data = new ArrayList<>();
public void testListView(){for (int i = 0; i < 100; i++) {ListViewBean bean = new ListViewBean();bean.setName("pansd"+i);data.add(bean);}ListView listView = findViewById(R.id.lv);//给listView组装item,就是textviewlistView.setAdapter(new MyAdapter(data,this));listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Log.e("pansd - item - click", "onItemClick: "+i );}});
}

设置适配ListView的适配器(将TextView适配到其的item)

package com.pshdhx.demo1.adapter;
​
import android.content.Context;
import android.database.DataSetObserver;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.TextView;
​
import com.pshdhx.demo1.Bean.ListViewBean;
import com.pshdhx.demo1.R;
​
import java.util.List;
​
public class MyAdapter extends BaseAdapter {
​private List<ListViewBean> data;private Context context;
​
​public MyAdapter(List<ListViewBean> data, Context context) {this.data = data;this.context = context;}
​@Overridepublic int getCount() {return data.size();}
​@Overridepublic Object getItem(int i) {return null;}
​@Overridepublic long getItemId(int i) {return i;}
​
​
​/***     //获取每个列表项的视图* @param i 下标* @param view 当前要显示或者是重用的列表项视图* @param viewGroup 表示listview本身* @return*/@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {if(view == null){ //第一次加载没有可重用的视图,LayoutInflater从布局文件中填充一个新试图,并将其分配给view对象//将子元素视图填充到父元素中view = LayoutInflater.from(context).inflate(R.layout.list_view_item,viewGroup,false);}//view存在,即视图对象存在,可以直接使用它,不用再创建视图对象,从容器中获取listviewTextView textView = view.findViewById(R.id.tv1);textView.setText(data.get(i).getName());Log.e("pansd", "getView: "+ i );return view;}
​//由于view.findViewById(R.id.tv1); 每次进来时,比较耗时,所以把TextView抽取出来public View getView2(int i, View view, ViewGroup viewGroup) {ViewHolder viewHolder;if(view == null){viewHolder = new ViewHolder();view = LayoutInflater.from(context).inflate(R.layout.list_view_item,viewGroup,false);viewHolder.textView = view.findViewById(R.id.tv1);}else{
//            通过调用view.setTag(viewHolder);将ViewHolder对象设置为视图的标签,以便在以后进行重用。viewHolder = (ViewHolder) view.getTag();}viewHolder.textView.setText(data.get(i).getName());Log.e("pansd", "getView: "+ i );return view;}private final class ViewHolder{TextView textView;}
}

其余:

public class ListViewBean {String name;
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
}

效果:

RecyclerView

1、导入包

build.gradle中

implementation 'androidx.recyclerview:recyclerview:1.1.0'

2、构造器,很重要,实现监听

package com.pshdhx.demo1.adapter;
​
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
​
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
​
import com.pshdhx.demo1.Bean.ListViewBean;
import com.pshdhx.demo1.R;
​
import java.util.List;
​
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {private List<ListViewBean> data;private Context context;
​
​public RecyclerAdapter(List<ListViewBean> data, Context context) {this.data = data;this.context = context;}
​@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = parent.inflate(context, R.layout.recycler_view_item, null);return new MyViewHolder(view);}
​@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, int position) {holder.tv.setText(data.get(position).getName());}
​@Overridepublic int getItemCount() {return data == null ? 0 : data.size();}
​public class MyViewHolder extends RecyclerView.ViewHolder {private TextView tv;public MyViewHolder(@NonNull View itemView) {super(itemView);tv = itemView.findViewById(R.id.tv1);itemView.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {if(onRecyclerItemClickListener != null){onRecyclerItemClickListener.onRecyclerItemClick(getAdapterPosition());}}});}}
​private OnRecyclerItemClickListener onRecyclerItemClickListener;
​public void setOnRecyclerItemClickListener(OnRecyclerItemClickListener listener){onRecyclerItemClickListener = listener;}
​public interface OnRecyclerItemClickListener{void onRecyclerItemClick(int position);}
}
3、主方法public void testRecyclerView(){for (int i = 0; i < 100; i++) {ListViewBean bean = new ListViewBean();bean.setName("pansd cycler"+i);data.add(bean);}RecyclerView recyclerView = findViewById(R.id.rv);//给listView组装item,就是textview
//        recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.setLayoutManager(new GridLayoutManager(this,3)); //三个显示一行RecyclerAdapter recyclerAdapter = new RecyclerAdapter(data, this);recyclerAdapter.setOnRecyclerItemClickListener(new RecyclerAdapter.OnRecyclerItemClickListener() {@Overridepublic void onRecyclerItemClick(int position) {Log.e("pansd", "onRecyclerItemClick: "+ position);}});recyclerView.setAdapter(recyclerAdapter);}
4、recycler_view_item.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tv1"android:textSize="30sp"/>
​
</LinearLayout>
5、容器activity_main3.xml<androidx.recyclerview.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/rv"
/>

动画类型

逐帧动画 frame-by-frame animation

F:\androidProject\android_learn\demo1\app\src\main\res\drawable\frame_list.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
​<!-- 创建逐帧动画 --><item android:drawable="@drawable/cat" android:duration="120"/><item android:drawable="@drawable/cat" android:duration="120"/><item android:drawable="@drawable/cat" android:duration="120"/>
</animation-list>
activity_main_framebyframe.xml<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"android:id="@+id/frameid"android:background="@drawable/frame_list"android:orientation="vertical"tools:context=".MainActivity">
​
​
</RelativeLayout>
/*** 测试逐帧动画*/
public void testframeByFrame(){setContentView(R.layout.activity_main_framebyframe);RelativeLayout relativeLayout = findViewById(R.id.frameid);final AnimationDrawable background = (AnimationDrawable) relativeLayout.getBackground();relativeLayout.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {if(flag){background.start();flag = false;Log.e(TAG, "onClick: 在运行" );}else{background.stop();flag = true;Log.e(TAG, "onClick: 已停止" );}}});
}

补间动画 tweened animation

1、透明度 alpha

2、旋转 rotate

3、缩放 scale

4、平移 translate

alpha.xml rotate.xml scale.xml translate.xml

<!-- 测试补间动画 透明度 [从透明变到不透明,整个过程需要花费两秒钟]-->
<alphaandroid:fromAlpha="0"android:toAlpha="1"android:duration="2000"/>
<rotateandroid:fromDegrees="0"android:toDegrees="360"android:pivotX="50%"android:pivotY="50%"android:duration="2000"/><scale
​android:fromXScale="1"android:fromYScale="1"android:toXScale="0.5"android:toYScale="0.5"android:pivotX="50%"android:pivotY="50%"android:duration="2000"/><translateandroid:fromXDelta="0"android:fromYDelta="0"android:toXDelta="400"android:toYDelta="400"android:duration="2000"/>/*** 测试补间动画*/public void testBujianDonghua(){setContentView(R.layout.activity_main_tweened_animation);final ImageView imageView = findViewById(R.id.iv);imageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {
//                Animation animation = AnimationUtils.loadAnimation(MainActivity.this,
//                        R.anim.alpha);
//                Animation animation = AnimationUtils.loadAnimation(MainActivity.this,
//                        R.anim.rotate);
//                Animation animation = AnimationUtils.loadAnimation(MainActivity.this,
//                        R.anim.scale);Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate);imageView.startAnimation(animation);}});
属性动画 property animation/*** 测试属性动画 1*/
public void testPropertyAnimation1(){setContentView(R.layout.activity_main_tweened_animation);ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);valueAnimator.setDuration(2000);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {float val = (float) valueAnimator.getAnimatedValue();Log.e(TAG, "onAnimationUpdate: "+val );}});valueAnimator.start();ImageView imageView = findViewById(R.id.iv);//将会由完全透明 变为不透明ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);objectAnimator.setDuration(4000);objectAnimator.start();
​objectAnimator.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animator) {Log.e(TAG, "onAnimationStart: ");}
​@Overridepublic void onAnimationEnd(Animator animator) {
​Log.e(TAG, "onAnimationEnd: " );}
​@Overridepublic void onAnimationCancel(Animator animator) {
​Log.e(TAG, "onAnimationCancel: " );}
​@Overridepublic void onAnimationRepeat(Animator animator) {
​}});objectAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation) {super.onAnimationStart(animation);Log.e(TAG, "只监听start方法...onAnimationStart: " );}});
​
}

单位尺寸

  1. px: pixels(像素).不同设备显示效果相同

  2. pt: point,是一个标准的长度单位,1pt= 1/72英寸,用于印刷业,非常简单易用

3、dip: device independent pixels(设备独立像素).不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素 4、dp:就是dip 5、sp: scaled pixels(放大像素).主要用于字体显示best for textsize。

6、LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息

   
 /*** 测试像素*/public void testPx_dp_sp(){LinearLayout linearLayout = new LinearLayout( this);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);linearLayout.setLayoutParams(layoutParams);TextView textview = new TextView(this);textview.setText("我是文本");// 这里的300设置的是pxLinearLayout.LayoutParams textLayoutParams = new LinearLayout.LayoutParams(  300, 300);
//        textview.setLayoutParams(textLayoutParams);
//        linearLayout.addView(textview);linearLayout.addView(textview,textLayoutParams);}

ViewPager

类似于左右滑动的轮播图===屏幕之间左右切换

重点:明白配置ViewPager作为容器的适配器

适配器代码:

public class ViewPagerAdapter  extends PagerAdapter {List<View> viewList;
​public ViewPagerAdapter(List<View> viewList) {this.viewList = viewList;}
​@Overridepublic int getCount() {return viewList.size();}
​@Overridepublic boolean isViewFromObject(@NonNull View view, @NonNull Object object) {return view == object;}
​@NonNull@Overridepublic Object instantiateItem(@NonNull ViewGroup container, int position) {container.addView(viewList.get(position),0);return viewList.get(position);}
​@Overridepublic void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {container.removeView(viewList.get(position));}
}

主方法:加载布局文件并将其转换成View对象的,用于在Android应用程序中显示用户界面,填充到主视图中。

/*** 测试ViewPager*/
public void testViewPager(){setContentView(R.layout.activity_main_view_pager);LayoutInflater lf = getLayoutInflater().from(this);View view1 = lf.inflate(R.layout.view_pager_layout1, null);View view2 = lf.inflate(R.layout.view_pager_layout2, null);View view3 = lf.inflate(R.layout.view_pager_layout3, null);List<View> viewList = new ArrayList<>();viewList.add(view1);viewList.add(view2);viewList.add(view3);
​ViewPager viewPager = findViewById(R.id.vp);ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(viewList);viewPager.setAdapter(viewPagerAdapter);
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"android:orientation="vertical"tools:context=".MainActivity">
​<!-- 效果,屏幕之间左右切换,像全屏的轮播图 --><androidx.viewpager.widget.ViewPagerandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/vp"/>
​
​
​
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:background="#ff0000"android:layout_height="match_parent">
​<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="layout1"android:textSize="80dp"/>
</LinearLayout>

Fragment

演示Fragment

类似于web中的iframe,点击一条栏目,该栏目的内容显示在Fragment中。

1、有自己的生命周期,可以嵌入到activity中,并且fragment可以复用

可以在activity在运行的时候动态添加删除,有自己的响应事件。

像是一个子activity

2、必须在activity中才能运行。所以其生命周期受到activity的限制。

代码:

新建Fragment,注意不是class

package com.pshdhx.demo1.fragment;
​
import android.os.Bundle;
​
import androidx.fragment.app.Fragment;
​
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
​
import com.pshdhx.demo1.R;
​
​
public class BlankFragment1 extends Fragment {
​private View root;TextView tv;
​@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
​}
​@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {if(root == null){root = inflater.inflate(R.layout.fragment_blank1,container,false);}tv = root.findViewById(R.id.tv_fragment);Button btn = root.findViewById(R.id.btn_fragment);
​btn.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {tv.setText("hello fragment hhh");}});
​return root;}
}

2、在新建Fragment的时候,自动把xml文件给添加好了,改布局为LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".fragment.BlankFragment1">
​<!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="100dp"android:text="hello_blank_fragment----first"android:id="@+id/tv_fragment"/>
​<Buttonandroid:layout_width="match_parent"android:layout_height="100dp"android:id="@+id/btn_fragment"android:text="fragment中的按钮"/>
​
</LinearLayout>

3、将Fragment的xml绑定到主布局中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"android:orientation="vertical"tools:context=".MainActivity">
<!--    测试fragment--><fragmentandroid:name="com.pshdhx.demo1.fragment.BlankFragment1"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/fm"/>
​
</LinearLayout>

4、主Activity绑定主布局

   
 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
//        setContentView(R.layout.activity_main3);
//        testRecyclerView();
//        testBujianDonghua();
//        testPropertyAnimation1();//testViewPager();testFragment();}
public void testFragment(){setContentView(R.layout.activity_main_fragment);
}

动态切换fragment

主方法:

public void testFragment2(){setContentView(R.layout.activity_main_fragment2);Button btn1 = findViewById(R.id.btn1);Button btn2 = findViewById(R.id.btn2);btn1.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {replaceFragment(new BlankFragment1());}});
​btn2.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {replaceFragment(new ItemFragment());}});
}//动态切换fragmentpublic void replaceFragment(Fragment fragment){FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.replace(R.id.frameLayout,fragment);transaction.addToBackStack(null);//入栈操作,方便手机下边的返回按钮操作,防止一点直接返回到桌面transaction.commit();}

主视图:

<Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/btn1"android:text="change"/>
​
<Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/btn2"android:text="replace"/>
​
<FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffff00"android:id="@+id/frameLayout"/>

新建两个Fragment 1个是空的 1个是item的,他们将放置在frameLayout的布局中,进行切换。

Activity与Fragment通信

Activity传递信息,使用Bundle对象

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Bundle bundle = getArguments();String message = (String) bundle.get("message");String message2 = bundle.getString("message");Log.e("pansd--", "onCreate: "+message+"---"+message2 );
​
}
Fragment获取信息,BlankFragment1.java@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Bundle bundle = getArguments();String message = (String) bundle.get("message");String message2 = bundle.getString("message");Log.e("pansd--", "onCreate: "+message+"---"+message2 );
​
}

Fragment与Activity相互通信

利用面向对象的接口 MainActivity.java

 /*** 1、测试Fragment的事件是小的activity* 2、测试fragment的切换* 3、利用IFragment接口测试fragment与Activity的通信*/public void testFragment2(){setContentView(R.layout.activity_main_fragment2);Button btn1 = findViewById(R.id.btn1);btn1.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {//activity给fragment传递信息BlankFragment1 bf1 = new BlankFragment1();bf1.setFragmentCallback(new IFragmentCallback() {@Overridepublic void sendMsgToActivity(String msg) {
//                        Log.e(TAG, "sendMsgToActivity: "+msg);Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();}
​@Overridepublic String getMsgFromActivity(String msg) {return "hello fragment,this msg is from activity";}});replaceFragment(bf1);}});}

BlankFragment1.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {if(root == null){root = inflater.inflate(R.layout.fragment_blank1,container,false);}Button btn = root.findViewById(R.id.btn_fragment);btn.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {String msg = fragmentCallback.getMsgFromActivity("null");Toast.makeText(BlankFragment1.this.getContext(),msg,Toast.LENGTH_SHORT).show();fragmentCallback.sendMsgToActivity("hello activity,this msg from fragment");
​}});
​return root;
}

Debug流程走一遍之后,点击按钮,会先调用blank_fragment中的onClick方法,里边的方法会跳转到MainActivity中的onclick的方法,进而实现类似传递的效果。前提是接口被调用.[black_fragment和MainActitity的onclick方法都会被调用到]

Fragment的生命周期

Fragment的使用过程

1、点击按钮,打开Fragment

onCreate->onCreateView->onActitityCreated->onStart->onResume【即将可见,并开始响应用户输入】

2、直接返回到手机桌面

onPause->onStop

3、重新打开桌面

onStart->onResume

4、按后退键【整个应用彻底退出】

onPause->onStop->onDestroyView->onDestory->onDetach

5、如果在事务中,使用replace【替换,activity替换,先销毁之前的view,再加载新的view】fragment

onPause->onStop->onDestoryView

6、替换了之后,在按返回键

onCreateView【和5的最后一个相对应】->onActivityCreated->onstart->onResume

7、直接叉掉app

onDestory->onDetach

Fragment与PageView联合使用

viewPager2简介

先写下ViewPager2组件的介绍,优点是可以懒加载。

1、适配器

public class ViewPager2Adapter  extends RecyclerView.Adapter<ViewPager2Adapter.ViewPage2ViewHolder> {
​
​private List<String> titleList = new ArrayList<>();private List<Integer> colorList = new ArrayList<>();
​private ViewPage2ViewHolder holder;
​public ViewPager2Adapter(List<String> titleList, List<Integer> colorList, ViewPage2ViewHolder holder) {this.titleList = titleList;this.colorList = colorList;this.holder = holder;}
​public ViewPager2Adapter() {
​for (int i = 0; i < 10; i++) {titleList.add("title---" + i);}colorList.add(R.color.white1 );colorList.add(R.color.white2 );colorList.add(R.color.white3 );colorList.add(R.color.white4 );colorList.add(R.color.white1 );colorList.add(R.color.teal_200 );colorList.add(R.color.purple_700 );colorList.add(R.color.purple_500 );colorList.add(R.color.purple_200 );colorList.add(R.color.white1);}
​@NonNull@Overridepublic ViewPage2ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return new ViewPage2ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager, parent, false));}
​@Overridepublic void onBindViewHolder(@NonNull ViewPage2ViewHolder holder, int position) {holder.tv.setText(titleList.get(position));holder.container.setBackgroundResource(colorList.get(position));}
​
​//这个有点重要呀,没有的话,界面为空!!@Overridepublic int getItemCount() {return colorList.size();}
​class ViewPage2ViewHolder extends RecyclerView.ViewHolder{
​TextView tv;RelativeLayout container;
​public ViewPage2ViewHolder(@NonNull View itemView) {super(itemView);container = itemView.findViewById(R.id.container);tv = itemView.findViewById(R.id.tv);}}

2、主类

public class MainActivity extends AppCompatActivity {
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
​ViewPager2 viewPage2 = findViewById(R.id.view_pager_2);viewPage2.setAdapter(new ViewPager2Adapter());
​}
}
ViewPager与Fragment实现翻页效果

1、自定义适配器(Fragment和View一块的)

package com.pshdhx.viewpager2.adapter;
​
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
​
import java.util.List;
​
public class MyFragmentPageAdapter  extends FragmentStateAdapter {private List<Fragment> fragmentList;
​public MyFragmentPageAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> fragmentList) {super(fragmentActivity);this.fragmentList = fragmentList;}
​public MyFragmentPageAdapter(@NonNull Fragment fragment, List<Fragment> fragmentList) {super(fragment);this.fragmentList = fragmentList;}
​public MyFragmentPageAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, List<Fragment> fragmentList) {super(fragmentManager, lifecycle);this.fragmentList = fragmentList;}
​@NonNull@Overridepublic Fragment createFragment(int position) {return fragmentList.get(position);}
​@Overridepublic int getItemCount() {return fragmentList.size();}
}

2、主方法

public class MainActivity extends AppCompatActivity {
​private ViewPager2 viewPager2;
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
​
//        ViewPager2 viewPager2 = findViewById(R.id.view_pager_2);
//        viewPager2.setAdapter(new ViewPager2Adapter());initPage();}
​/*** 测试Viewpage2与Fragment结合使用*/private void initPage() {viewPager2 = findViewById(R.id.view_pager_2);List<Fragment> fragmentList = new ArrayList<>();fragmentList.add(BlankFragment.newInstance("微信聊天"));fragmentList.add(BlankFragment.newInstance("通讯录"));fragmentList.add(BlankFragment.newInstance("发现"));fragmentList.add(BlankFragment.newInstance("我"));MyFragmentPageAdapter myFragmentPageAdapter = new MyFragmentPageAdapter(getSupportFragmentManager(), getLifecycle(), fragmentList);viewPager2.setAdapter(myFragmentPageAdapter);}
}

3、Fragment的配置方法

public class BlankFragment extends Fragment {
​private View rootView;
​private static final String ARG_TEXT = "param1";private String mTextString ;
​public BlankFragment() {}
​
​public static BlankFragment newInstance(String param1) {BlankFragment fragment = new BlankFragment();Bundle args = new Bundle();args.putString(ARG_TEXT, param1);fragment.setArguments(args);return fragment;}
​@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {mTextString = getArguments().getString(ARG_TEXT);}}
​@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {if(rootView == null){rootView = inflater.inflate(R.layout.fragment_blank, container, false);}initView();return rootView;}
​private void initView() {TextView textView = rootView.findViewById(R.id.fragment_tv);textView.setText(mTextString);}
}

案例:实现微信主界面跟随底部按钮的切换,或者是滑动切换。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
​private ViewPager2 viewPager2;
​private LinearLayout llchat,llContacts,llFind,llProfile;private ImageView ivChat,ivContacts,ivFind,ivProfile,ivCurrent;
​
​
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
​
//        ViewPager2 viewPager2 = findViewById(R.id.view_pager_2);
//        viewPager2.setAdapter(new ViewPager2Adapter());initPage();initTabView();}
​
​
​/*** 测试Viewpage2与Fragment结合使用*/private void initPage() {viewPager2 = findViewById(R.id.view_pager_2);List<Fragment> fragmentList = new ArrayList<>();//设置fragment,主显示区域的内容fragmentList.add(BlankFragment.newInstance("微信聊天"));fragmentList.add(BlankFragment.newInstance("通讯录"));fragmentList.add(BlankFragment.newInstance("发现"));fragmentList.add(BlankFragment.newInstance("我"));MyFragmentPageAdapter myFragmentPageAdapter = new MyFragmentPageAdapter(getSupportFragmentManager(), getLifecycle(), fragmentList);viewPager2.setAdapter(myFragmentPageAdapter);//设置viewPager2的滑动窗口效果viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {super.onPageScrolled(position, positionOffset, positionOffsetPixels);}
​@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);changeTab(position);}
​@Overridepublic void onPageScrollStateChanged(int state) {super.onPageScrollStateChanged(state);}});}
​//初始化底部边框【四个tab=四个LinearLayout,还有每个tab中的图片】private void initTabView() {llchat = findViewById(R.id.id_tab_weixin);llchat.setOnClickListener(this);llContacts = findViewById(R.id.id_tab_contact);llContacts.setOnClickListener(this);llFind = findViewById(R.id.id_tab_find);llFind.setOnClickListener(this);llProfile = findViewById(R.id.id_tab_profile);llProfile.setOnClickListener(this);
​ivChat = findViewById(R.id.id_iv_weixin);ivContacts = findViewById(R.id.id_iv_contact);ivFind = findViewById(R.id.id_iv_find);ivProfile = findViewById(R.id.id_iv_profile);
​//设置第一张图片为默认选中,且为当前图片ImageViewivChat.setSelected(true);ivCurrent = ivChat;}
​
​public void changeTab(int position){//取消图片选中ivCurrent.setSelected(false);switch (position){case R.id.id_tab_weixin:case 0://当前图片是选中状态ivChat.setSelected(true);//当前图片为此图片ivCurrent = ivChat;//当前fragment为第0个Fragment的内容viewPager2.setCurrentItem(0);break;case R.id.id_tab_contact:case 1:ivContacts.setSelected(true);ivCurrent = ivContacts;viewPager2.setCurrentItem(1);break;case R.id.id_tab_find:case 2:ivFind.setSelected(true);ivCurrent = ivFind;viewPager2.setCurrentItem(2);break;case R.id.id_tab_profile:case 3:ivProfile.setSelected(true);ivCurrent = ivProfile;viewPager2.setCurrentItem(3);break;}}
​@Overridepublic void onClick(View view) {changeTab(view.getId());}

底部footer的xml,主要被主视图include即可

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="55dp"android:background="#ff0000"android:orientation="horizontal">
​
<!--    设置四个footer的子组件--><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_gravity="center"android:gravity="center"android:orientation="vertical"android:id="@+id/id_tab_weixin"><ImageViewandroid:layout_width="32dp"android:layout_height="32dp"android:id="@+id/id_iv_weixin"android:background="@drawable/tab_weixin"></ImageView><TextViewandroid:layout_width="32dp"android:layout_height="wrap_content"android:id="@+id/text_weixin"android:gravity="center"android:text="微信"/></LinearLayout>
​<LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_gravity="center"android:gravity="center"android:orientation="vertical"android:id="@+id/id_tab_contact"><ImageViewandroid:layout_width="32dp"android:layout_height="32dp"android:id="@+id/id_iv_contact"android:background="@drawable/tab_contact"></ImageView><TextViewandroid:layout_width="32dp"android:layout_height="wrap_content"android:id="@+id/text_contact"android:gravity="center"android:text="通讯录"/></LinearLayout>
​<LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_gravity="center"android:gravity="center"android:orientation="vertical"android:id="@+id/id_tab_find"><ImageViewandroid:layout_width="32dp"android:layout_height="32dp"android:id="@+id/id_iv_find"android:background="@drawable/tab_find"></ImageView><TextViewandroid:layout_width="32dp"android:layout_height="wrap_content"android:id="@+id/text_find"android:gravity="center"android:text="发信"/></LinearLayout>
​<LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:layout_gravity="center"android:gravity="center"android:orientation="vertical"android:id="@+id/id_tab_profile"><ImageViewandroid:layout_width="32dp"android:layout_height="32dp"android:id="@+id/id_iv_profile"android:background="@drawable/tab_profile"></ImageView><TextViewandroid:layout_width="32dp"android:layout_height="wrap_content"android:id="@+id/text_profile"android:gravity="center"android:text="我"/></LinearLayout>
​
</LinearLayout>

include底部footer视图

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"android:orientation="vertical"tools:context=".MainActivity">
​
<!--    设置显示区域页面--><androidx.viewpager2.widget.ViewPager2android:id="@+id/view_pager_2"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#00ff00" />
​
<!--    引入footer的组件--><include layout="@layout/bottom_layout"/>
​
</LinearLayout>

Activity

一个activity对应一个布局文件,一个activity必须要到清单文件中注册。

实例:一个activity跳转到另外一个activity

<applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" />
​<category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>
​<activity android:name=".MainActivity2"></activity>
</application>
public void startActivity(){startActivity(new Intent(this,MainActivity2.class));
}

Activity的生命周期

Service

service和activity类似,也是一个组件,运行在后台,需要在清单文件中注册使用【注意包名和路径】

<service android:name=".service.MyService01"/>

生命周期:

startService【执行onCreate->onStartCommand->onStart】

stopService【执行onDestory】

bindService【执行onCreate->onBind】

unbindService【执行onUnbind->onDestory】

消息广播

//测试动态广播
public class MyRevicer_Dynamic extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.e("pansd-动态接收者", "onReceive: ");}
}

注册到清单中,xml注册可能失效,但是java注册是可以的。

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main4);
​MyRevicer_Dynamic revicer_dynamic = new MyRevicer_Dynamic();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("com.pshdhx.revicer_dynamic");registerReceiver(revicer_dynamic,intentFilter);
}
​
​
//动态广播按钮
public void sendDynamicAction(View view) {Intent intent = new Intent();intent.setAction("com.pshdhx.revicer_dynamic");sendBroadcast(intent);
}
<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="动态注册广播 发送广播区域"android:textSize="20dp"android:layout_marginTop="100dp"android:layout_gravity="center_horizontal"/>
<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="发送动态广播"android:onClick="sendDynamicAction"

android常用框架

热修复

见官方的demo文档。

主要流程是,将app的id注册到腾讯的buglg中,修复bug完成后,将修复包上传到buglg中,然后有bug的app会收到提醒,然后去buglg中下载补丁包,下载完成后,会强制重启app,此时已经完成修复。

官网:https://graph.qq.com/

官方文档:Android SDK 使用指南 - Bugly 文档

github的Demo地址:https://github.com/BuglyDevTeam/Bugly-Android-Demo/tree/master/BuglyHotfixDemo

高德地图SDK

1、搜索高德地图开放平台,注册登录

2、创建应用,获取keytool的秘钥,会生成appid,配置到gradle

3、通过gradle下载高德地图的依赖,或者是通过相关下载获取arr包到lib目录下,在用gradle增加lib目录,并引入arr包,可以避免冲突

4、开启配置{相关权限的读取配置、设置高德key的配置【生成的applicationID】到AndroidManifest.xml清单中}

5、设置layout.xml,引入地图。在Activity中按照文档和demo开始给地图添加功能。

6、POI关键词搜索功能

Glide图片加载库

可以加载本APP下的,手机内存中的,或是网络中的图片资源。

Glide v4 : 快速高效的Android图片加载库

GitHub - bumptech/glide: An image loading and caching library for Android focused on smooth scrolling

implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
ImageView imageView = findViewById(R.id.iv);
Glide.with(this).load("https://img0.baidu.com/it/u=1435639120,2241364006&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500").into(imageView);
​
​
//        Glide.with(this)
//                .load("https://img0.baidu.com/it/u=1435639120,2241364006&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500")
//                .apply(requestOptions)
//                .transition(DrawableTransitionOptions.withCrossFade(fadeFactory))
//                .transform(new CircleCrop())//设置圆
//
//                .into(imageView);
简化操作:@GlideExtension
public class MyAppGlideExtension extends AppGlideModule {
​
​private MyAppGlideExtension(){
​}
​@GlideOptionpublic static BaseRequestOptions<?> defaultImg(BaseRequestOptions<?> options){return options.placeholder(R.drawable.ic_launcher_foreground).error(R.drawable.error).fallback(R.drawable.fallback_null);}
}
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
}
make project下,然后使用//使用此类,必须先make project下
GlideApp.with(this).load("xxxx").defaultImg()
.into(imageView);

网络加载框架

OKHttp

Http上传数据的编码格式类型【content-type】

HTTP content-type | 菜鸟教程

  • application/json: JSON数据格式

  • multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

public class MainActivity extends AppCompatActivity {
​private OkHttpClient httpClient;private String TAG = "pansd--";private TextView textView;
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
​httpClient = new OkHttpClient();textView = findViewById(R.id.reponseText);View getSyncBtn = findViewById(R.id.getSync);View getASyncBtn = findViewById(R.id.getASync);View postSyncBtn = findViewById(R.id.postSync);View postASyncBtn = findViewById(R.id.postASync);Request request = new Request.Builder().url("https://www.httpbin.org/get?a=1&b=2").build();
​
​
​getSyncBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new Thread(){@Overridepublic void run() {Call call = httpClient.newCall(request);try {Response response = call.execute();Log.e(TAG, "testOkHttp: "+response.body().string() );} catch (IOException e) {e.printStackTrace();}}}.start();}});
​getASyncBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Call call = httpClient.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {
​}
​@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {if(response.isSuccessful()){Log.e(TAG, "onResponse: "+response.body().string() );}}});}});
​postSyncBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new Thread(){@Overridepublic void run() {FormBody formBody = new FormBody.Builder().add("a", "1").add("b", "2").build();Request requestPostSync = new Request.Builder().url("https://www.httpbin.org/post").post(formBody).build();Call call = httpClient.newCall(requestPostSync);try {Response response = call.execute();Log.e(TAG, "run: "+response.body().string() );} catch (IOException e) {e.printStackTrace();}}}.start();}});
​postASyncBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {FormBody formBody = new FormBody.Builder().add("a", "1").add("b", "2").build();Request requestPostSync = new Request.Builder().url("https://www.httpbin.org/post").post(formBody).build();Call call = httpClient.newCall(requestPostSync);call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {
​}
​@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
​if(response.isSuccessful()){Log.e(TAG, "onResponse: "+response.body().string() );}}});}});
​Button uploadFileBtn = findViewById(R.id.fileUpload);uploadFileBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.e(TAG, "onClick: "+ Environment.getExternalStorageDirectory() );File file = new File("C:\\Users\\Lenovo\\Desktop\\null.png");MultipartBody multipartBody = new MultipartBody.Builder().addFormDataPart("file", file.getName(), RequestBody.create(file, MediaType.parse("image/png"))).build();
​Request fileRequest = new Request.Builder().url("https://www.httpbin.org/post").post(multipartBody).build();Call call = httpClient.newCall(fileRequest);call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {
​Log.e(TAG, "onFailure: "+e +"");}
​@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {if(response.isSuccessful()){Log.e(TAG, "文件上传__onClick: "+response.body().string() );}}});}});}

OKHTTP的自定义配置

okhttp新增拦截器+保存cookie

public void testInterceptorAndCookie(View view) {
​new Thread() {@Overridepublic void run() {Interceptor interceptor = new Interceptor() {@NotNull@Overridepublic Response intercept(@NotNull Chain chain) throws IOException {Request request = chain.request().newBuilder().addHeader("os", "android").addHeader("username", "pansd").build();Response response = chain.proceed(request);return response;}
//        Request request = new Request.Builder().url("https://httpbin.org/get?a=1&b=2").build();
//        Call call = okHttpClient.newCall(request);
//
//        call.enqueue(new Callback() {
//            @Override
//            public void onFailure(@NotNull Call call, @NotNull IOException e) {
//                Log.e(TAG, "onFailure: "+"error"+e );
//            }
//
//            @Override
//            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//
//                if(response.isSuccessful()){
//                    Log.e(TAG, "testInterceptorAndCookie: "+response.body().string() );
//                }
//            }
//        });};
​OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(interceptor).cache(new Cache(new File("C:\\Users\\Lenovo\\Desktop"), 1024 * 1024)).cookieJar(new CookieJar() {@Overridepublic void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {cookieList = list;}
​@NotNull@Overridepublic List<Cookie> loadForRequest(@NotNull HttpUrl httpUrl) {if ("www.wanandroid.com".equals(httpUrl.host())) {return cookieList;}return cookieList;}}).build();
​
​FormBody formBody = new FormBody.Builder().add("username", "hello_pans").add("password", "pan123").build();Request request1 = new Request.Builder().url("https://www.wanandroid.com/user/login").post(formBody).build();
​Call call1 = okHttpClient.newCall(request1);try {Response response = call1.execute();Log.e(TAG, "testInterceptorAndCookie: " + response.body().string());} catch (IOException e) {e.printStackTrace();}
​
​
//        call1.enqueue(new Callback() {
//            @Override
//            public void onFailure(@NotNull Call call, @NotNull IOException e) {
//                Log.e(TAG, "testInterceptorAndCookie: "+e);
//
//            }
//
//            @Override
//            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//
//                Log.e(TAG, "testInterceptorAndCookie: "+response.body().string() );
//
//            }
//        });
​Request req = new Request.Builder().url("https://www.wanandroid.com/lg/collect/list/0/json").build();
​Call newCall = okHttpClient.newCall(req);newCall.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {
​Log.e(TAG, "onFailure: "+e );}
​@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {Log.e(TAG, "onResponse: " + response.body().string());}});}}.start();
​
​}

Retrofit

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

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

相关文章

AWS向量数据库Amazon OpenSearch Service使用测评

前言 在大模型盛行的当今&#xff0c;选择适宜的数据库显得尤为重要。因为你需要面对海量训练数据&#xff0c;快速的检索至关紧要&#xff0c;以及对于存储的要求也是至关重要的。对于海量的数据查询和存储是需要巨大的算力支持。向量数据库常用在一些图像文本或者视频的生成…

【大数据存储与处理】实验二 HBase 过滤器操作

实验二 HBase 过滤器操作 【实验目的】&#xff1a; 1.掌握使用 HBase 过滤器进行全表扫描。 【实验内容与要求】&#xff1a; 在 HBase 中&#xff0c;Get 和 Scan 操作都可以使用过滤器来设置输出的范围&#xff0c;类似于 SQL 里面 的 Where 查询条件。使用 show_filte…

【VScode和Leecode的爱恨情仇】command ‘leetcode.signin‘ not found

文章目录 一、关于command ‘leetcode.signin‘ not found的问题二、解决方案第一&#xff0c;没有下载Nodejs&#xff1b;第二&#xff0c;有没有在VScode中配置Nodejs第三&#xff0c;力扣的默认在VScode请求地址中请求头错误首先搞定配置其次搞定登入登入方法一&#xff1a;…

obswebsocket+douyinAPI+python,教你如何三步搭建自己的AI美女直播间,24小时的永动机

一&#xff1a;什么是AI直播美女直播间 就是在直播的时候通过弹幕进行选择不同的ai人物进行跳舞的直播间大致就是 可以看到左边是有提示&#xff0c;根据观众刷礼物的不同进行选择某一个AI人物进行展示&#xff0c;怎么通过技术手段实现呢 二&#xff1a;你需要懂的 其实还…

vmware安装银河麒麟V10高级服务器操作系统

vmware安装银河麒麟V10高级服务器操作系统 1、下载银河麒麟V10镜像2、VMware安装银河麒麟V10高级服务器操作系统2.1、新建虚拟机2.2、安装虚拟机 3、配置银河麒麟V10高级服务器操作系统3.1、安装vmware tools3.2、配置静态IP地址 和 dns3.3、查看磁盘分区 1、下载银河麒麟V10镜…

AI工具网站汇总——学习的好帮手

一、聊天AI 1.ChatGPT 地表最强AI聊天机器人 网址&#xff1a;https://chat.openai.com 2.Anthropic Anthropic发布的与ChatGPT竞争的聊天机器人 网址&#xff1a;https://www.anthropic.com 3.文心一言 百度全新知识增强大语言模型&#xff01;国产聊天机器人 网址&…

so-vits-svc的使用

1. 启动工程 找到工程的路径&#xff0c;找到启动的bat文件&#xff0c;这里以 d:/so-vits-svc为例。 2. 启动过程 启动后会出现cmp的一个弹框&#xff0c;初始启动相对较慢&#xff0c;请耐心等待一会儿&#xff0c;启动完成后&#xff0c;会出现一个页面&#xff0c;如下…

JDK各个版本特性讲解-JDK14特性

JDK各个版本特性讲解-JDK14特性 一、Java14概述二、语法层面的变化1. instanceof2. switch表达式3. 文本块的改进4. Records记录类型 二、关于GC1.G1的NUMA内存分配优化2. 弃用SerialCMS,ParNewSerial Old3.删除CMS4.ZGC on macOS and Windows 三、其他变化1.友好的空指针异常提…

HAproxy做七层代理+keepalived高可用,实现动静分离,由nginx处理静态页面,tomcat处理动态页面

目录 一、三种软负载均衡器的区别 关于三种负载均衡器的性能对比&#xff1a; 关于三种负载均衡器的代理类型对比&#xff1a; 关于三种负载均衡器的健康检查对比&#xff1a; 二、haproxy的8中负载均衡调度算法 haproxy的会话保持的方式 haproxy的配置文件学习 三、实操…

(详解版)创建线程的四种方式

文章目录 Java中创建线程的四种方式1. 继承Thread类并重写 run 方法来创建线程2. 实现Runnable接口并实现 run 方法来创建线程。3. 使用Callable接口创建线程4. 使用Executor框架创建线程 Java中创建线程的四种方式 接下来我会详细解释这四种方式创建线程如何实现. 我们如果要…

【HarmonyOS开发】ArkTs关系型和非关系型数据库的存储封装

前面使用了首选项的存储方式&#xff0c;因此将其他的两种存储方式&#xff08;键值型数据库和关系型数据库&#xff09;也学习一下&#xff0c;简单记录一下&#xff0c;并进行封装&#xff0c;方便后续使用。 1、效果预览 2、使用条件 2.1 键值型数据库 键值型数据库实现数据…

RabbitMQ入门指南(三):Java入门示例

专栏导航 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、AMQP协议 1.AMQP 2.Spring AMQP 二、使用Spring AMQP实现对RabbitMQ的消息收发 1.案例准备阶段 2.入门案例&#xff08;无交换机&#xff09; 3.任务模型案例&#xff08;Work Queues&#xff0…

九.数据处理之增删改

数据处理之增删改 1.插入数据1.1实际问题1.2方式1&#xff1a;VALUES的方式添加1.3方式2&#xff1a;将查询结果插入到表中 2.更新数据3.删除数据4.MySQL8新特性&#xff1a;计算列5.综合案例 1.插入数据 1.1实际问题 解决方式&#xff1a;使用INSERT语句向表中插入数据 1.2方…

文献速递:生成对抗网络医学影像中的应用——用于生成前列腺MR-only影像治疗剂量规划的合成CT的深度学习模型:多中心研究

文献速递&#xff1a;生成对抗网络医学影像中的应用——用于生成前列腺MR-only影像治疗剂量规划的合成CT的深度学习模型&#xff1a;多中心研究 本周给大家分享文献的主题是生成对抗网络&#xff08;Generative adversarial networks, GANs&#xff09;在医学影像中的应用。文…

电源模块测试方法 | 怎么测试电源负载瞬态响应?

负载瞬态响应测试是检测电源稳定性和质量的重要方法之一&#xff0c;而电源稳定性是设备正常运行的基础。通过负载瞬态响应测试来检测电源的响应速度和稳定性&#xff0c;从而优化电源设计&#xff0c;提升性能&#xff0c;确保电子设备可以稳定工作。 什么是负载瞬态响应测试?…

js知识点1:防抖节流

js知识点1&#xff1a;防抖节流 防抖节流 防抖节流&#xff0c;本质上是优化高频率执行代码的一种手段 定义&#xff1a; 防抖: n 秒后再执行该事件&#xff0c;若在 n 秒内被重复触发&#xff0c;则重新计时 节流: n 秒内只运行一次&#xff0c;若在 n 秒内重复触发&#xff0…

【C语言】SCU安全项目2-BufBomb

目录 关键代码解读&#xff1a; getxs() getbuf() test() 核心思路 具体操作1 具体操作2 前段时间忙于强网杯、英语4级和一些其他支线&#xff0c;有点摸不清头绪了&#xff0c;特别是qwb只有一个输出&#xff0c;太过坐牢&#xff0c;决定这个安全项目做完后就继续投身…

Spring MVC框架支持RESTful,设计URL时可以使用{自定义名称}的占位符@Get(“/{id:[0-9]+}/delete“)

背景&#xff1a;在开发实践中&#xff0c;如果没有明确的规定URL&#xff0c;可以参考&#xff1a; 传统接口 获取数据列表,固定接口路径&#xff1a;/数据类型的复数 例如&#xff1a;/albums/select RESTful接口 - 根据ID获取某条数据&#xff1a;/数据类型的复数/{id} - 例…

在Linux安装的Docker中开启IPv6

先在Linux中安装docker&#xff0c;然后在docker中开启IPv6。 安装docker 第一步&#xff0c;卸载旧版本docker。 若系统中已安装旧版本docker&#xff0c;则需要卸载旧版本docker以及与旧版本docker相关的依赖项。 命令&#xff1a;yum -y remove docker docker-client do…

CountDownLatch和Semaphore的区别?

CountDownLatch和Semaphore都是在Java中用于多线程协同的工具&#xff0c;但它们有一些重要的区别。 CountDownLatch&#xff1a; 用途&#xff1a; 主要用于等待一个或多个线程完成操作&#xff0c;它的计数器只能被减少&#xff0c;不能被增加。计数&#xff1a; 初始化时需…