Android MVP框架搭建与使用(含源码)

  • @author llw

*/

public interface BaseView {

}

然后创建一个BasePresenter,在这里可以操作View,这是MVP中的核心思想,通过P层控制M和V,从而减低M和V的耦合,甚至让它们不存在直接关联。

package com.llw.mvplibrary.base;

import java.lang.ref.WeakReference;

/**

  • Presenter基类 操作视图View

  • @param

  • @author llw

*/

public class BasePresenter {

//弱引用View

protected WeakReference mWeakReference;

private V mView;

/**

  • 绑定View

  • @param view

*/

public void attachView(V view) {

mView = view;

mWeakReference = new WeakReference(view);

}

/**

  • 解绑View

*/

public void detachView() {

mView = null;

if (mWeakReference != null) {

mWeakReference.clear();

mWeakReference = null;

}

}

/**

  • 获取view

  • @return

*/

public V getView() {

if (mWeakReference != null) {

return mWeakReference.get();

}

return null;

}

/**

  • View是否绑定

  • @return

*/

public boolean isViewAttached() {

return mView != null;

}

}

下面写BaseActivity,一般的Activity只要继承这个BaseActivity,重写里面的方法即可。

package com.llw.mvplibrary.base;

import android.app.Activity;

import android.app.Dialog;

import android.os.Bundle;

import android.view.View;

import android.widget.Toast;

import androidx.annotation.Nullable;

import androidx.appcompat.app.AppCompatActivity;

import androidx.appcompat.widget.Toolbar;

import com.llw.mvplibrary.R;

import java.util.Objects;

/**

  • 基类Activity,普通Activity继承即可。

  • @author llw

*/

public abstract class BaseActivity extends AppCompatActivity implements IUiCallback {

//Activity 上下文

protected Activity context;

//弹窗

private Dialog mDialog;

private static final int FAST_CLICK_DELAY_TIME = 500;

private static long lastClickTime;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//绑定视图

initBeforeView(savedInstanceState);

//获取Activity的上下文

this.context = this;

BaseApplication.getActivityManager().addActivity(this);

//绑定视图XML

if (getLayoutId() > 0) {

setContentView(getLayoutId());

}

initData(savedInstanceState);

}

/**

  • Toast消息提示 字符

  • @param llw

*/

protected void showMsg(CharSequence llw) {

Toast.makeText(context, llw, Toast.LENGTH_SHORT).show();

}

/**

  • Toast消息提示 资源ID

  • @param resourceId

*/

protected void showMsg(int resourceId){

Toast.makeText(context, resourceId, Toast.LENGTH_SHORT).show();

}

/**

  • 弹窗出现

*/

protected void showLoadingDialog() {

if (mDialog == null) {

mDialog = new Dialog(context, R.style.loading_dialog);

}

mDialog.setContentView(R.layout.dialog_loading);

mDialog.setCancelable(false);

Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(android.R.color.transparent);

mDialog.show();

}

/**

  • 弹窗隐藏

*/

protected void hideLoadingDialog() {

if (mDialog != null) {

mDialog.dismiss();

}

mDialog = null;

}

/**

  • 返回 不需要参数

*/

protected void Back(){

context.finish();

if(!isFastClick()){

context.finish();

}

}

/**

  • 返回 toolbar控件点击

  • @param toolbar

*/

protected void Back(Toolbar toolbar) {

toolbar.setNavigationOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

context.finish();

if (!isFastClick()) {

context.finish();

}

}

});

}

/**

  • 两次点击间隔不能少于500ms

  • @return flag

*/

protected static boolean isFastClick() {

boolean flag = true;

long currentClickTime = System.currentTimeMillis();

if ((currentClickTime - lastClickTime) >= FAST_CLICK_DELAY_TIME) {

flag = false;

}

lastClickTime = currentClickTime;

return flag;

}

}

一般来说这样就可以了,但是以我的开发习惯来说我还会加上这个页面加载的弹窗和页面销毁的控制,那么下午我给加上。

首先需要在drawable下添加两个图片,这两个图片有一些特殊,建议你直接在我的源码里面复制出来,因为我现在贴出来你拿过去直接用是达不到实际的效果的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

然后com.llw.mvplibrary下新建一个view包,然后新建一个LoadingView类,里面的代码如下:

package com.llw.mvplibrary.view;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Matrix;

import android.util.AttributeSet;

import androidx.annotation.Nullable;

import com.llw.mvplibrary.R;

import java.lang.ref.SoftReference;

/**

  • 加载框

  • @author llw

*/

public class LoadingView extends androidx.appcompat.widget.AppCompatImageView {

private int mCenterRotateX;//图片旋转点x

private int mCenterRotateY;//图片旋转点y

private LoadingRunnable mRunnable;

public LoadingView(Context context) {

this(context, null);

}

public LoadingView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

setScaleType(ScaleType.MATRIX);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_loading);

setImageBitmap(bitmap);

mCenterRotateX = bitmap.getWidth() / 2;

mCenterRotateY = bitmap.getHeight() / 2;

}

/**

  • onDraw()之前调用

*/

@Override

protected void onAttachedToWindow() {

super.onAttachedToWindow();

if (mRunnable==null){

mRunnable=new LoadingRunnable(this);

}

if (!mRunnable.isLoading){

mRunnable.start();

}

}

/**

  • view销毁时调用

*/

@Override

protected void onDetachedFromWindow() {

super.onDetachedFromWindow();

if (mRunnable!=null){

mRunnable.stop();

}

mRunnable=null;

}

class LoadingRunnable implements Runnable {

private boolean isLoading;

private Matrix mMatrix;

private SoftReference mLoadingViewSoftReference;

private float mDegrees = 0f;

public LoadingRunnable(LoadingView loadingView) {

mLoadingViewSoftReference = new SoftReference(loadingView);

mMatrix = new Matrix();

}

@Override

public void run() {

if (mLoadingViewSoftReference.get().mRunnable != null && mMatrix != null) {

mDegrees += 30f;

mMatrix.setRotate(mDegrees, mCenterRotateX, mCenterRotateY);

mLoadingViewSoftReference.get().setImageMatrix(mMatrix);

if (mDegrees==360){

mDegrees=0f;

}

if (isLoading) {

mLoadingViewSoftReference.get().postDelayed(mLoadingViewSoftReference.get().mRunnable, 100);

}

}

}

public void stop() {

isLoading = false;

}

public void start() {

isLoading = true;

if (mLoadingViewSoftReference.get().mRunnable != null && mMatrix != null) {

mLoadingViewSoftReference.get().postDelayed(mLoadingViewSoftReference.get().mRunnable, 100);

}

}

}

}

再新建一个LoadingTextView,里面的代码如下:

package com.llw.mvplibrary.view;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.LinearGradient;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.Shader;

import android.util.AttributeSet;

import androidx.appcompat.widget.AppCompatTextView;

/**

  • 颜色波浪TextView

  • @author llw

*/

public class LoadingTextView extends AppCompatTextView {

private LinearGradient mLinearGradient;

private Matrix mGradientMatrix;

private Paint mPaint;

private int mViewWidth = 0;

private int mTranslate = 0;

private boolean mAnimating = true;

public LoadingTextView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

if (mViewWidth == 0) {

mViewWidth = getMeasuredWidth();

if (mViewWidth > 0) {

mPaint = getPaint();

mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0,

new int[]{0x33ffffff, 0xffd81e06, 0x33ffffff},

new float[]{0, 0.5f, 1}, Shader.TileMode.CLAMP);

mPaint.setShader(mLinearGradient);

mGradientMatrix = new Matrix();

}

}

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (mAnimating && mGradientMatrix != null) {

mTranslate += mViewWidth / 10;

if (mTranslate > 2 * mViewWidth) {

mTranslate = -mViewWidth;

}

mGradientMatrix.setTranslate(mTranslate, 0);

mLinearGradient.setLocalMatrix(mGradientMatrix);

postInvalidateDelayed(20);

}

}

}

然后在res下新建一个layout文件夹,在这个文件夹下新建一个dialog_loading.xml,里面的布局代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:id=“@+id/layout_loading”

android:layout_width=“120dp”

android:layout_height=“120dp”

android:layout_gravity=“center”

android:background=“@drawable/ic_loading_bg”

android:gravity=“center”

android:orientation=“vertical”>

<com.llw.mvplibrary.view.LoadingView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content” />

<com.llw.mvplibrary.view.LoadingTextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginTop=“12dp”

android:text=“Loading”

android:textColor=“#fff”

android:textSize=“@dimen/sp_14” />

还需要在valuse下新建一个styles.xml,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>

然后在BaseActivity中新增如下两个方法。

//弹窗

private Dialog mDialog;

/**

  • 弹窗出现

*/

protected void showLoadingDialog() {

if (mDialog == null) {

mDialog = new Dialog(context, R.style.loading_dialog);

}

mDialog.setContentView(R.layout.dialog_loading);

mDialog.setCancelable(false);

Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(android.R.color.transparent);

mDialog.show();

}

/**

  • 弹窗隐藏

*/

protected void hideLoadingDialog() {

if (mDialog != null) {

mDialog.dismiss();

}

mDialog = null;

}

然后再增加页面返回的处理。

private static final int FAST_CLICK_DELAY_TIME = 500;

private static long lastClickTime;

/**

  • 返回 不需要参数

*/

protected void Back(){

context.finish();

if(!isFastClick()){

context.finish();

}

}

/**

  • 返回 toolbar控件点击

  • @param toolbar

*/

protected void Back(Toolbar toolbar) {

toolbar.setNavigationOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

context.finish();

if (!isFastClick()) {

context.finish();

}

}

});

}

/**

  • 两次点击间隔不能少于500ms

  • @return flag

*/

protected static boolean isFastClick() {

boolean flag = true;

long currentClickTime = System.currentTimeMillis();

if ((currentClickTime - lastClickTime) >= FAST_CLICK_DELAY_TIME) {

flag = false;

}

lastClickTime = currentClickTime;

return flag;

}

这一步为止,这个BaseActivity就写完了,下面该写BaseFragment了。

package com.llw.mvplibrary.base;

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import androidx.annotation.NonNull;

import androidx.annotation.Nullable;

import androidx.fragment.app.Fragment;

/**

  • 基类Fragment,普通Fragment继承即可。

  • @author llw

*/

public abstract class BaseFragment extends Fragment implements IUiCallback {

protected View rootView;

protected LayoutInflater layoutInflater;

protected Activity context;

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

initBeforeView(savedInstanceState);

}

@Nullable

@Override

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

layoutInflater = inflater;

if(rootView == null){

rootView = inflater.inflate(getLayoutId(),null);

}else {

ViewGroup viewGroup = (ViewGroup) rootView.getParent();

if(viewGroup != null){

viewGroup.removeView(rootView);

}

}

return rootView;

}

@Override

public void onActivityCreated(@Nullable Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);

initData(savedInstanceState);

}

/**

  • 绑定

  • @param context

*/

@Override

public void onAttach(@NonNull Context context) {

super.onAttach(context);

if(context instanceof Activity){

this.context = (Activity) context;

}

}

/**

  • 解绑

*/

@Override

public void onDetach() {

super.onDetach();

context = null;

}

@Override

public void initBeforeView(Bundle savedInstanceState) {

}

}

现在这个base包下的内容就写完了,该到mvp包了。

4. 创建mvp包(以及包下的Activity和Fragment)

在com.llw.mvplibrary下创建一个mvp包,在这个包下创建一个MvpActivity抽象类,代码如下:

package com.llw.mvplibrary.mvp;

import android.os.Bundle;

import com.llw.mvplibrary.base.BaseActivity;

import com.llw.mvplibrary.base.BasePresenter;

import com.llw.mvplibrary.base.BaseView;

/**

  • 适用于需要访问网络接口的Activity

  • @author llw

*/

public abstract class MvpActivity

extends BaseActivity {

protected P mPresenter;

/**

  • 创建Presenter

*/

protected abstract P createPresenter();

@Override

public void initBeforeView(Bundle savedInstanceState) {

//创建

mPresenter = createPresenter();

//绑定View

mPresenter.attachView((BaseView) this);

}

/**

  • 页面销毁时解除绑定

*/

@Override

protected void onDestroy() {

super.onDestroy();

mPresenter.detachView();

}

}

然后创建一个MvpFragment抽象类

package com.llw.mvplibrary.mvp;

import android.os.Bundle;

import com.llw.mvplibrary.base.BaseFragment;

import com.llw.mvplibrary.base.BasePresenter;

import com.llw.mvplibrary.base.BaseView;

/**

  • 适用于需要访问网络接口的Fragment

  • @author llw

*/

public abstract class MvpFragment

extends BaseFragment {

protected P mPresenter;

/**

  • 创建Presenter

*/

protected abstract P createPresent();

@Override

public void initBeforeView(Bundle savedInstanceState) {

mPresenter = createPresent();

mPresenter.attachView((BaseView) this);

}

@Override

public void onDestroy() {

super.onDestroy();

mPresenter.detachView();

}

}

它里面的代码其实和MvpActivity差不多,唯一区别就是继承的父类不同。

mvp包中的代码就写完了,下面就到网络请求的使用了,这里我会采用我之前写的一个网络访问框架,把它融合到这个Mvp框架中,成为一体,如果你还没有了解过网络访问框架的话,不妨看看这一篇文章Android OkHttp+Retrofit+RxJava搭建网络访问框架,相信对你有所帮助,那么为了避免一些麻烦我直接去Github上面把源码下载下来。

5. 结合网络访问框架

进入源码地址:NetworkFrameWorkDemo

在这里插入图片描述

下载到本地,然后解压。

在这里插入图片描述

然后打开到最下面的network包

在这里插入图片描述

将这个文件夹复制到com.llw.mvplibrary下。如下图所示

在这里插入图片描述

然后找到res下这四个文件夹,全部复制

在这里插入图片描述

粘贴到你项目的res下

在这里插入图片描述

然后修改一下network包下一些类的包异常问题,建议你把这个里面的每一个类或者接口都打开一次,报红的就是里面的包路径需要修改的。

然后可以在app模块中使用了,使用过程可能一开始有一些麻烦,但是当你熟悉之后就好了。

三、使用MVP框架


通过上面的一系列搭建MVP框架依赖模块的过程,目前就已经完成了,那么接下来就到了使用阶段,既然是使用那么自然而然就是在app模块中了,当前这个模块中只有一个MainActivity。

1. 创建application包以及下面的类

在com.llw.mvpdemo下新建一个application包,在这个包下创建一个NetworkRequiredInfo类,里面实现network包下的INetworkRequiredInfo接口,目的就是获取APP运行时的一些信息,里面的代码如下:

package com.llw.mvpdemo.application;

import android.app.Application;

import com.llw.mvplibrary.BuildConfig;

import com.llw.mvplibrary.network.INetworkRequiredInfo;

/**

  • 网络访问信息

  • @author llw

*/

public class NetworkRequiredInfo implements INetworkRequiredInfo {

private Application application;

public NetworkRequiredInfo(Application application){

this.application = application;

}

/**

  • 版本名

*/

@Override

public String getAppVersionName() {

return BuildConfig.VERSION_NAME;

}

/**

  • 版本号

*/

@Override

public String getAppVersionCode() {

return String.valueOf(BuildConfig.VERSION_CODE);

}

/**

  • 是否为debug

*/

@Override

public boolean isDebug() {

return BuildConfig.DEBUG;

}

/**

  • 应用全局上下文

*/

@Override

public Application getApplicationContext() {

return application;

}

}

然后同样在这个application包下新建一个MyApplication类

package com.llw.mvpdemo.application;

import com.llw.mvplibrary.BaseApplication;

import com.llw.mvplibrary.network.NetworkApi;

/**

  • 自定义Application

  • @author llw

*/

public class MyApplication extends BaseApplication {

@Override

public void onCreate() {

super.onCreate();

//初始化

NetworkApi.init(new NetworkRequiredInfo(this));

}

}

这里面主要完成对网络的初始化,在这个init方法中,完成了对环境的配置

在这里插入图片描述

你如果你对这一块并不了解,你可以先看看Android OkHttp+Retrofit+RxJava搭建网络访问框架这篇文章,相信你就明白了,因为内容实在比较多,因此写到一起你可能不太有耐心看完。

刚才写了MyApplication,自然要在AndroidManifest.xml中配置才行,如果你不配置则就是使用系统的Application。

在这里插入图片描述

这样就配置好了

2. 创建ApiService接口

最好有一个地方可以集中写一些接口,因为在实际开发中,一个服务器中不可能就一个接口,因此前面的地址和后面的参数是可以分开的。

下面在com.llw.mvpdemo下新建一个api包,这个包下新建一个ApiService接口

package com.llw.mvpdemo.api;

import com.llw.mvpdemo.bean.WallPaperResponse;

import io.reactivex.Observable;

import retrofit2.http.GET;

/**

  • ApiService接口 统一管理应用所有的接口

  • @author llw

*/

public interface ApiService {

/**

  • 获取热门壁纸列表

*/

@GET(“/v1/vertical/vertical?limit=30&skip=180&adult=false&first=0&order=hot”)

Observable getWallPaper();

}

现在你的这个WallPaperResponse肯定是报红的,因为没有所以需要创建一个,这个实体Bean的意思就是当你请求网络接口,会将返回的数据解析成这样的一个实体,而Observable则是用来出来OkHttp的返回数据的。如果你使用Retrofit来处理返回这里就要改成Call,这种方式你可以参考我在天气APP中的网络写法看看。

之前的请求地址现在已经访问不了了,也有读者和我反映这个情况,痛定思痛之后,我决定更改一个访问API,将返回的数据进行一次修改。新的访问地址如下:

http://service.picasso.adesk.com/v1/vertical/vertical?limit=30&skip=180&adult=false&first=0&order=hot

这个可以用浏览器访问一下:

在这里插入图片描述

可以拿到结果,这说明这个API目前还是可以使用的,那么下面增加一个新的返回实体Bean。

下面创建一个这样返回数据类。这里最好的方式是在com.llw.mvpdemo下再建一个bean包或者model包,看个人习惯了,我个人习惯建bean包,然后包下新建一个WallPaperResponse类,类的代码如下:

public class WallPaperResponse {

private String msg;

private ResBean res;

private int code;

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

public ResBean getRes() {

return res;

}

public void setRes(ResBean res) {

this.res = res;

}

public int getCode() {

return code;

}

public void setCode(int code) {

this.code = code;

}

public static class ResBean {

private List vertical;

public List getVertical() {

return vertical;

}

public void setVertical(List vertical) {

this.vertical = vertical;

}

public static class VerticalBean {

private String preview;

private String thumb;

private String img;

private int views;

private String rule;

private int ncos;

private int rank;

private String source_type;

private String wp;

private boolean xr;

private boolean cr;

private int favs;

private double atime;

private String id;

private String store;

private String desc;

private List cid;

private List<?> tag;

private List<?> url;

public String getPreview() {

return preview;

}

public void setPreview(String preview) {

this.preview = preview;

}

public String getThumb() {

return thumb;

}

public void setThumb(String thumb) {

this.thumb = thumb;

}

public String getImg() {

return img;

}

public void setImg(String img) {

this.img = img;

}

public int getViews() {

return views;

}

public void setViews(int views) {

this.views = views;

}

public String getRule() {

return rule;

}

public void setRule(String rule) {

this.rule = rule;

}

public int getNcos() {

return ncos;

}

public void setNcos(int ncos) {

this.ncos = ncos;

}

public int getRank() {

return rank;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。

image

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

time;

private String id;

private String store;

private String desc;

private List cid;

private List<?> tag;

private List<?> url;

public String getPreview() {

return preview;

}

public void setPreview(String preview) {

this.preview = preview;

}

public String getThumb() {

return thumb;

}

public void setThumb(String thumb) {

this.thumb = thumb;

}

public String getImg() {

return img;

}

public void setImg(String img) {

this.img = img;

}

public int getViews() {

return views;

}

public void setViews(int views) {

this.views = views;

}

public String getRule() {

return rule;

}

public void setRule(String rule) {

this.rule = rule;

}

public int getNcos() {

return ncos;

}

public void setNcos(int ncos) {

this.ncos = ncos;

}

public int getRank() {

return rank;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-jB1ynqbp-1712507619605)]

[外链图片转存中…(img-FfRf4NBM-1712507619606)]

[外链图片转存中…(img-NcXagLhy-1712507619606)]

[外链图片转存中…(img-H0EzlXlB-1712507619606)]

[外链图片转存中…(img-EznEj1tx-1712507619607)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。

[外链图片转存中…(img-s4zVawnl-1712507619607)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值