Android的基础开发

2023-12-19

基础开发

listView

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

首先设置两个视图布局

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

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/lv"/>
list_view_item.xml【充当容器中的组件{TextView}】

<TextView
    android: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,就是textview
    listView.setAdapter(new MyAdapter(data,this));
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public 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;
    }
​
    @Override
    public int getCount() {
        return data.size();
    }
​
    @Override
    public Object getItem(int i) {
        return null;
    }
​
    @Override
    public long getItemId(int i) {
        return i;
    }
​
​
​
    /**
     *     //获取每个列表项的视图
     * @param i 下标
     * @param view 当前要显示或者是重用的列表项视图
     * @param viewGroup 表示listview本身
     * @return
     */
    @Override
    public 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存在,即视图对象存在,可以直接使用它,不用再创建视图对象,从容器中获取listview
        TextView 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
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = parent.inflate(context, R.layout.recycler_view_item, null);
        return new MyViewHolder(view);
    }
​
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.tv.setText(data.get(position).getName());
    }
​
    @Override
    public 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(){
                @Override
                public 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() {
            @Override
            public 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">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv1"
        android:textSize="30sp"
        />
​
</LinearLayout>
5、容器activity_main3.xml

<androidx.recyclerview.widget.RecyclerView
    android: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(){
        @Override
        public 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

<!-- 测试补间动画 透明度 [从透明变到不透明,整个过程需要花费两秒钟]-->
<alpha
    android:fromAlpha="0"
    android:toAlpha="1"
    android:duration="2000"
    />
<rotate
        android: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"
        />
    <translate
        android: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() {
            @Override
            public 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() {
        @Override
        public 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() {
        @Override
        public void onAnimationStart(Animator animator) {
            Log.e(TAG, "onAnimationStart: ");
        }
​
        @Override
        public void onAnimationEnd(Animator animator) {
​
            Log.e(TAG, "onAnimationEnd: " );
        }
​
        @Override
        public void onAnimationCancel(Animator animator) {
​
            Log.e(TAG, "onAnimationCancel: " );
        }
​
        @Override
        public void onAnimationRepeat(Animator animator) {
​
        }
    });
    objectAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public 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设置的是px
        LinearLayout.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;
    }
​
    @Override
    public int getCount() {
        return viewList.size();
    }
​
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }
​
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        container.addView(viewList.get(position),0);
        return viewList.get(position);
    }
​
    @Override
    public 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.ViewPager
        android: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">
​
    <TextView
        android: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;
​
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
​
    }
​
    @Override
    public 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(){
            @Override
            public 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 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="hello_blank_fragment----first"
        android:id="@+id/tv_fragment"
        />
​
    <Button
        android: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-->
    <fragment
        android:name="com.pshdhx.demo1.fragment.BlankFragment1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fm"
        />
​
</LinearLayout>

4、主Activity绑定主布局


     
 @Override
    protected 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(){
        @Override
        public void onClick(View view) {
            replaceFragment(new BlankFragment1());
        }
    });
​
    btn2.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view) {
            replaceFragment(new ItemFragment());
        }
    });
}
   //动态切换fragment
    public void replaceFragment(Fragment fragment){
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.frameLayout,fragment);
        transaction.addToBackStack(null);//入栈操作,方便手机下边的返回按钮操作,防止一点直接返回到桌面
        transaction.commit();
    }

主视图:

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn1"
    android:text="change"/>
​
<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn2"
    android:text="replace"/>
​
<FrameLayout
    android: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(){
            @Override
            public void onClick(View view) {
                //activity给fragment传递信息
                BlankFragment1 bf1 = new BlankFragment1();
                bf1.setFragmentCallback(new IFragmentCallback() {
                    @Override
                    public void sendMsgToActivity(String msg) {
//                        Log.e(TAG, "sendMsgToActivity: "+msg);
                        Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
                    }
​
                    @Override
                    public 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(){
        @Override
        public 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
    @Override
    public ViewPage2ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewPage2ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager, parent, false));
    }
​
    @Override
    public void onBindViewHolder(@NonNull ViewPage2ViewHolder holder, int position) {
        holder.tv.setText(titleList.get(position));
        holder.container.setBackgroundResource(colorList.get(position));
    }
​
​
    //这个有点重要呀,没有的话,界面为空!!
    @Override
    public 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 {
​
    @Override
    protected 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
    @Override
    public Fragment createFragment(int position) {
        return fragmentList.get(position);
    }
​
    @Override
    public int getItemCount() {
        return fragmentList.size();
    }
}

2、主方法

public class MainActivity extends AppCompatActivity {
​
    private ViewPager2 viewPager2;
​
    @Override
    protected 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;
    }
​
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mTextString = getArguments().getString(ARG_TEXT);
        }
    }
​
    @Override
    public 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;
​
​
​
    @Override
    protected 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() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
​
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                changeTab(position);
            }
​
            @Override
            public 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);
​
        //设置第一张图片为默认选中,且为当前图片ImageView
        ivChat.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;
        }
    }
​
    @Override
    public 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的子组件-->
    <LinearLayout
        android: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">
        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:id="@+id/id_iv_weixin"
            android:background="@drawable/tab_weixin">
        </ImageView>
        <TextView
            android:layout_width="32dp"
            android:layout_height="wrap_content"
            android:id="@+id/text_weixin"
            android:gravity="center"
            android:text="微信"/>
    </LinearLayout>
​
    <LinearLayout
        android: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">
        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:id="@+id/id_iv_contact"
            android:background="@drawable/tab_contact">
        </ImageView>
        <TextView
            android:layout_width="32dp"
            android:layout_height="wrap_content"
            android:id="@+id/text_contact"
            android:gravity="center"
            android:text="通讯录"/>
    </LinearLayout>
​
    <LinearLayout
        android: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">
        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:id="@+id/id_iv_find"
            android:background="@drawable/tab_find">
        </ImageView>
        <TextView
            android:layout_width="32dp"
            android:layout_height="wrap_content"
            android:id="@+id/text_find"
            android:gravity="center"
            android:text="发信"/>
    </LinearLayout>
​
    <LinearLayout
        android: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">
        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:id="@+id/id_iv_profile"
            android:background="@drawable/tab_profile">
        </ImageView>
        <TextView
            android: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.ViewPager2
        android: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

<application
    android: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 {
    @Override
    public 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);
}
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="动态注册广播 发送广播区域"
    android:textSize="20dp"
    android:layout_marginTop="100dp"
    android:layout_gravity="center_horizontal"/>
<Button
    android: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(){
​
    }
​
    @GlideOption
    public 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;
​
    @Override
    protected 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() {
            @Override
            public void onClick(View v) {
                new Thread(){
                    @Override
                    public 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() {
            @Override
            public void onClick(View v) {
                Call call = httpClient.newCall(request);
                call.enqueue(new Callback() {
                    @Override
                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
​
                    }
​
                    @Override
                    public 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() {
            @Override
            public void onClick(View v) {
                new Thread(){
                    @Override
                    public 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() {
            @Override
            public 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() {
                    @Override
                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
​
                    }
​
                    @Override
                    public 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() {
            @Override
            public 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() {
                    @Override
                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
​
                        Log.e(TAG, "onFailure: "+e +"");
                    }
​
                    @Override
                    public 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() {
            @Override
            public void run() {
                Interceptor interceptor = new Interceptor() {
                    @NotNull
                    @Override
                    public 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() {
                            @Override
                            public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {
                                cookieList = list;
                            }
​
                            @NotNull
                            @Override
                            public 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() {
                    @Override
                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
​
                        Log.e(TAG, "onFailure: "+e );
                    }
​
                    @Override
                    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                        Log.e(TAG, "onResponse: " + response.body().string());
                    }
                });
            }
        }.start();
​
​
    }

Retrofit

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android的基础开发 的相关文章

  • PHP服务器端IAB验证openssl_verify总是返回0

    我使用以下函数 服务器端 php 来验证 IAB v3 事务 我从 Android 应用程序传递过来 Override protected void onActivityResult int requestCode int resultCo
  • Android STFP 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在我的 Android 项目中使用 SFTP 安卓已经有了吗 SFTP 库 还是我必须实现它 I
  • 在Android中将半径边框绘制到imageview或textview的一个角落

    我需要在我的应用程序中为图像视图或文本视图绘制边框 但我只需要在一个角落绘制它 就像图像一样 我做了一个形状 但我在所有 4 个边上都有边框
  • 删除视图并重新创建它

    有没有办法删除设置的视图 setContentView R layout set map center mapView MapView findViewById R id mapview 如果我再次调用此视图 则会收到一条错误消息 java
  • Android Ble GATT_ERROR 133 经常使用三星设备

    我正在研究 BLE 应用程序 我已经使用 Nexus Moto Samsung LG 等不同设备进行了测试 我仅在三星设备中收到 GATT 错误 133 三星 A5 2016 尝试连接 10 次 但只连接了 2 或 3 次 请帮助我 Non
  • 如何使用gradle这样的格式更改apk名称?

    当我使用 gradle 构建应用程序时 我想将 app release apk 文件名更改为如下所示 format appname of package name V version code yyMMdd R T explain appn
  • IntentService、Service 或 AsyncTask

    实现这一点的最佳方法是什么 我有一个 Android 应用程序 它将使用我的 python 服务器来允许两部手机之间进行轮流通信 回合意味着他们在一轮开始之前不能互相交谈 一旦他们发送一条消息 他们就不能发送另一条消息 直到对方做出回应 然
  • Android:拍照后调用裁剪活动

    我在解析拍摄照片的 uri 来裁剪活动时遇到问题 在我的应用程序中 用户可以拍摄一张照片或从图库中选择一张照片 然后裁剪并上传 一切听起来都很简单 从图库中选择时 图库应用程序会返回所选照片的 uri 如下所示 content media
  • 无法找到/下载 AppCompat-v7:23.1.1

    怎么了 我遇到了很多 找不到 appcompat v7 23 1 1 的问题 许多解决方案都不起作用 经过几个小时的思考和寻找答案 我遇到了一个奇怪的问题 I have gotAndroid 支持库 23 1 1 已安装 所有功能 exce
  • 如何在我的 Android 应用程序中实现应用内购买?

    如何在我的 Android 应用程序中实现应用内购买 我提到 http developer android com guide market billing billing integrate html billing service ht
  • Kotlin 和惯用的书写方式,基于可变值“如果不为空,则...”

    假设我们有这样的代码 class QuickExample fun function argument SomeOtherClass if argument mutableProperty null doSomething argument
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • 使用 DiffUtil 在 RecyclerView 上添加拖放

    我有一个从房间数据库更新的列表 我从 Room 收到更新的数据作为新列表 然后将其传递给列表适配器 https developer android com reference androidx recyclerview widget Lis
  • cordova插件条码扫描仪打不开扫描

    我的条形码扫描仪插件有问题 我不是天才 我不太了解如何编写网络应用程序 我使用phonegap和cordova 并且尝试制作一个网络应用程序 在单击链接后扫描条形码 我之前已经使用此命令行安装了该插件 cordova plugin add
  • Proguard - 找不到任何超级类

    我收到此错误 Unexpected error while performing partial evaluation Class org apache log4j chainsaw Main Method
  • Android 发布到 facebook 墙,stream.publish 几天来就中断了

    我有很多使用 FB android sdk 发布的应用程序 github com facebook facebook android sdk 我所有使用 FB 的应用程序几天后就停止工作了 这必然是 FB 方面的更改或错误 因为我的应用程序
  • 确定视图是否在屏幕上 - Android

    我对这个有点困惑 首先也是最重要的是 以下链接很有用 但是我提出了一些可见性问题 链接 检查视图可见性 https stackoverflow com questions 4628800 android how to check if a
  • 在 Android ADT Eclipse 插件中滚动布局编辑器

    有谁知道当布局编辑器的内容溢出一个 屏幕 时如何滚动这些内容 我说的是在设计时使用 ADT 布局编辑器 而不是在物理设备上运行时滚动 效果很好 关闭 Android 布局编辑器中的剪辑 切换剪辑 按钮位于 Android 布局编辑器的右上角
  • 从多个 TextView 中选择文本

    如何在android中从多个文本视图中选择文本 我已经尝试过以下代码 该代码一次仅适用于一个文本视图 我想一次性从许多文本视图中复制文本 android textIsSelectable true 你不能同时这样做 您需要在单个文本视图中设
  • compileReleaseKotlin 失败并出现 java.lang.ClassNotFoundException:com.sun.tools.javac.util.Context

    我正在尝试使用 gradlew 通过终端构建我的 Android 项目 其中包含库模块 在 Android Studio 中 它编译并安装成功 但是当我尝试运行时 gradlew assembleDebug我得到以下堆栈跟踪 Using k

随机推荐

  • 网络安全学习路线,入门到入坟,史上最全网络安全学习路线整理

    很多小伙伴在网上搜索网络安全时 会出来网络安全工程师这样一个职位 它的范围很广 只要是与网络安全挂钩的技术人员都算网络安全工程师 一些小伙伴就有疑问了 网络安全现在真的很火吗 那么寒哥就带大家看看 这一行到底有没有传说中的那么火 首先带大家
  • 为什么我的对话框创建失败了?菜鸟错误1

    对话框中的资源要么被定义为一个整数 要么被定义为一个字符串 仅仅一个简单的错误将会将其中的一个类型错误的变成另一个类型 我们来看一个例子 gt gt 请移步至 www topomel com 以查看图片 lt lt 你是否能发现其中的两处
  • 基于微信小程序的洗衣店在线洗衣系统设计与实现

    博主介绍 全网粉丝10W CSDN全栈领域优质创作者 博客之星 掘金 华为云 阿里云等平台优质作者 精彩专栏 推荐订阅 计算机毕设精品项目案例 持续更新 文末获取源码 数据库 文档 感兴趣的可以先收藏起来 还有大家在毕设选题 项目以及论文编
  • 手机与这三物共处一室,风险重重,多数人竟仍蒙在鼓里

    随着智能手机的普及 人们的生活已经离不开手机了 手机不仅可以随时随地联系朋友 查找信息 购物支付 还可以拍照 录音 录像 满足我们的各种需求 然而 手机的使用也伴随着一些风险 特别是当我们不注意手机的使用和存放时 可能会造成意想不到的损失
  • MySQL查询语句基础解析

    一般查询 直接查询 语法 select 字段 from 表名 举例 select name age from student 解析 从 student 表中查询 name 与 age 条件查询 语法 select 字段 from 表名 wh
  • JavaOOP篇----第四篇

    系列文章目录 文章目录 系列文章目录 前言 一 Char类型能不能转成int类型 能不能转化成string类型 能不能转成double类型 二 什么是拆装箱 三 Java中的包装类都是那些 前言 前些天发现了一个巨牛的人工智能学习网站 通俗
  • 网络安全面试题

    在当今社会网络安全行业越来越发达 也有越来越多的人去学习 为了更好地进行工作 除了学好知识外还要应对企业的面试 所以在这里我归总了一些网络安全方面的常见面试题 希望对大家有所帮助 windows常见 1 描述tcp udp的区别及优劣 及其
  • 100套风景+人物动物AI绘画关键词

    1 10美元计划 Midjourney的10美元计划是最基础的计划 每月可以生成200张图 然而没有fast模式 也无法免排队生成图 相对于30美元和60美元计划 这个计划更适合个人用户或小型团队使用 仅用于少量图像的生成 如果你只是偶尔需
  • 中国1KM分辨率年均降水量数据集(1901-2022)

    数据名称 中国1KM分辨率年均降水量数据集 1901 2022 数据时间 1901年至今 数据空间位置 全国 数据格式 tiff 数据空间分辨率 1kM 数据坐标系 WGS1984 数据简介 该数据集为全国逐年平均降水量数据 空间分辨率为0
  • 如何实现MQTT网关连接各类工业物联设备,实现数据传输与控制

    MQTT是一种轻量级的发布 订阅消息传输协议 专门为低带宽 高延迟或不稳定的网络环境设计 它支持离线消息存储 使客户端在未连接到服务器时也能接收到消息 MQTT网关是一种采用MQTT协议的网关设备 可以连接不同类型的工业物联设备 实现设备之
  • 基于Spring Boot、Mybatis、Redis和Layui的企业电子招投标系统源码实现与立项流程

    招投标管理系统是一款适用于招标代理 政府采购 企业采购和工程交易等领域的企业级应用平台 该平台以项目为主线 从项目立项到项目归档 实现了全流程的高效沟通和协作 通过该平台 用户可以实时共享项目数据信息 实现规范化管理和有效监控 协同工作网络
  • 使用AI大模型生成动漫人像

    在线体验 点击 图像处理 即可使用 public static final String SELFIE ANIME https aip baidubce com rest 2 0 image process v1 selfie anime
  • 高薪程序员也躲不过35岁这一关..当能力与年龄脱节,我们该如何自救

    在测试行业 甚至是整个互联网行业 存在这样一个神奇又隐秘的传说 过了 35 岁 你就找不到好工作了 没有哪一个企业出来声明 没有企业敢 也没有哪个超过 35 岁的员工出来反驳 似乎这已经是这个行业的通识 35岁已经成为一条冷酷的分界线 也是
  • Kubernetes 简介

    1 Kubernetes简介 一个容器管理应用 提高容器化服务的部署和管理效率 2 容器部署 2 1 传统部署形式 应用共用服务器环境 对于底层资源 文件目录 JDK 网络带宽等 存在弹性争夺 冲突等问题 容易导致应用性能不稳定 服务器环境
  • 中国90米分辨率可蚀性因子K数据

    数据时间 2023年 数据空间位置 全国 数据空间分辨率 90m 数据坐标系 WGS1984 数据格式 tiff 数据来源 地球资源数据云平台 www gis5g com 如需要请自行联系 数据简介 土壤可蚀性因子 K 数据 基于多种土壤属
  • 【网络安全】-Linux操作系统—CentOS安装、配置

    CentOS是一个基于Red Hat Enterprise Linux构建的免费操作系统 它提供了企业级的稳定性和安全性 非常适合用于服务器环境 以下是CentOS安装和基本配置的详细指南 准备工作 在安装CentOS之前 需要准备安装介质
  • 二蛋赠书十二期:《一本书讲透Java线程:原理与实践》

    摘要 互联网的每一个角落 无论是大型电商平台的秒杀活动 社交平台的实时消息推送 还是在线视频平台的流量洪峰 背后都离不开多线程技术的支持 在数字化转型的过程中 高并发 高性能是衡量系统性能的核心指标 越来越多的公司对从业人员的多线程编程能力
  • PHP中1688平台商品详情数据API接口采集到数据后如何处理

    PHP的定义和特点 PHP Hypertext Preprocessor 是一种开源的服务器端脚本语言 用于快速构建动态网页和Web应用程序 PHP采用嵌入HTML的方式 可以直接嵌入到HTML代码中 与数据库连接 数据处理 文件上传等操作
  • Vue的网络请求、插槽、Vuex

    axios npm i axios 跨域问题 协议名 ip 端口号 实际上 浏览器是收到数据的 但是没有交付给开发者 解决跨域问题 创建代理服务器 代理服务器和前端端口是一样的 所以不存在跨域问题 代理服务器与后端服务器都是服务器 和浏览器
  • Android的基础开发

    基础开发 listView ListView就是列表条目 可以向下滚动 也可以点击 首先设置两个视图布局 activity main2 xml 充当容器 ListView