Android开发之深度项目设计探索(二)

简介: 在《Android开发之深度项目设计探索(一)》 这篇文章中,主要描述了深度项目架构设计会涉及到的一些知识点,那么这篇文章主要介绍的是 RxLifecycle 使用及源码分析。

《Android开发之深度项目设计探索(一)》 这篇文章中,主要描述了深度项目架构设计会涉及到的一些知识点,那么这篇文章主要介绍的是 RxLifecycle 使用及源码分析。

RxLifecycle :

在Android进行面试的时候,经常会被问到的就是Android的内存泄漏、泄漏场景、泄漏原因以及解决办法。如果你提到了Rxjava2,面试官可能会接连发问Rxjava2在使用过程中会有一些什么问题?这时就可以谈到Rxjava如果在一些特定场景没有及时解绑订阅可能会导致内存泄漏。

泄漏的原因是:当RxJava发布一个订阅后,此时页面执行了finish的生命周期,但订阅逻辑还未完成。如果没有及时取消订阅,就会导致Activity/Fragment无法被回收,从而引发内存泄漏。但是相应的,Rxjava系列也提供了解决办法,那就是使用RxLifecycle 。

RxLifecycle官方文档

通过官方文档了解发现,RxLifecycle库的使用和集成也是简单和快捷的

A:RxLifecycle对应的依赖(最新版本)

// 这是RxLifecycle最主要的依赖
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2'

// If you want to bind to Android-specific lifecycles
//如果你想绑定Android的生命周期
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2'

// If you want pre-written Activities and Fragments you can subclass as providers
//如果想在预先写好的Activities and Fragments,你可以作为其父类的子类
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'

// If you want pre-written support preference Fragments you can subclass as providers
//如果想在预先支持的 Fragments,你可以作为其父类的子类
implementation 'com.trello.rxlifecycle2:rxlifecycle-components-preference:2.2.2'

// If you want to use Navi for providers
// Android使用的库,继承NaviActivity使用
implementation 'com.trello.rxlifecycle2:rxlifecycle-navi:2.2.2'

// If you want to use Android Lifecycle for providers
//如果你想为其提供Android生命周期
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2'

// If you want to use Kotlin syntax
//如果你想使用Kotlin语法
implementation 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.2'

// If you want to use Kotlin syntax with Android Lifecycle
//如果你想使用Kotlin语法作用在Android生命周期上
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.2'

下面是一些基本的使用和说明:

首先是 绑定生命周期:

 myObservable.compose(RxLifecycle.bind(lifecycle)).subscribe();

接着是 绑定特殊的生命周期(onStart onStop等等):

myObservable.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
    .subscribe();

然后是 通过RxLifecycle在适当的时间来结束:

myObservable.compose(RxLifecycleAndroid.bindActivity(lifecycle)).subscribe();

通过文档我们可以知道:如果在onStart( )这个生命周期里面绑定,它就会在onStop()这个终止绑定;如果我们在onPause( )之后订阅, 那么它就会在其下一个生命周期终止绑定,(在onPause( )之后订阅,因为onStop()是其下一个生命周期,如果Activity执行到了这里,就会解绑)

下面上一段代码加深RxLifecycle的理解和使用:

public class LifeActivity extends RxAppCompatActivity{

    @Override
    protected void onStart() {
        super.onStart();

        Observable.interval(2, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.bindToLifecycle())
                .subscribe();
    }

}

理论上我们需要使用compose操作符,然后加上bindToLifecycle即可完成简单的使用(注意:这里的 LifeActivity继承的是RxAppCompatActivity)看到了这里,可能疑惑的是,RxLifecycle具体的绑定该如何理解?里面的生命周期又是如何操作的?

是这样,这里的生命周期是由 LifecycleProvider<T> 来提供的,实现的方式有以下四种:
1:继承父类,RxActivity, RxFragment
2:使用 Navi 以及 Rxlifecycle-navi
3:使用 Android's lifecycle
4:自己编写实现

首先看第一种:也就是上面的代码,直接继承RxAppCompatActivity,然后点开RxAppCompatActivity源码会发现很多事情,这个后面说。

第二种:继承NaviActivity(需要导入上面提供的Navi对应的依赖)下面是参考代码

public class NaviLifeActivity extends NaviActivity{

    private final LifecycleProvider<ActivityEvent> provider
            = NaviLifecycle.createActivityLifecycleProvider(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initLifecycle();
    }
      
    private void initLifecycle(){
        Observable.interval(2, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(provider.bindToLifecycle())
                .subscribe();
    }
}

第三种和第四种由于涉及到另外的内容这里就不描述了。

值得一提的是:compose方法需在subscribeOn方法之后使用。

RxLifecycle源码分析:

说到源码,我们首先进入RxAppCompatActivity看看,因为compose(this.bindToLifecycle()) 这句API里面的this,代表的就是当前继承了RxAppCompatActivity的子类,奔着研究分析的精神,下面是
RxAppCompatActivity 的源码:

public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {

    private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

    @Override
    @NonNull
    @CheckResult
    public final Observable<ActivityEvent> lifecycle() {
        return lifecycleSubject.hide();
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindToLifecycle() {
        return RxLifecycleAndroid.bindActivity(lifecycleSubject);
    }

    @Override
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleSubject.onNext(ActivityEvent.CREATE);
    }

    @Override
    @CallSuper
    protected void onStart() {
        super.onStart();
        lifecycleSubject.onNext(ActivityEvent.START);
    }

    @Override
    @CallSuper
    protected void onResume() {
        super.onResume();
        lifecycleSubject.onNext(ActivityEvent.RESUME);
    }

    @Override
    @CallSuper
    protected void onPause() {
        lifecycleSubject.onNext(ActivityEvent.PAUSE);
        super.onPause();
    }

    @Override
    @CallSuper
    protected void onStop() {
        lifecycleSubject.onNext(ActivityEvent.STOP);
        super.onStop();
    }

    @Override
    @CallSuper
    protected void onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY);
        super.onDestroy();
    }
}

可以看到在Activity具体生命周期里面进行了对应的事件发送!

1:BehaviorSubject与ActivityEvent

RxAppCompatActivity源码中内部第一行代码是创建了一个BehaviorSubject实例对象,里面的泛型是ActivityEvent,首先看下 ActivityEvent

/**
 * Lifecycle events that can be emitted by Activities.
 */
public enum ActivityEvent {

    CREATE,
    START,
    RESUME,
    PAUSE,
    STOP,
    DESTROY

}

哦,细心的你一眼就看到了这是个枚举,里面的value对应的就是Activity生命周期的那些生命周期(因为在生命周期里面进行了发射嘛);那么,什么是BehaviorSubject?BehaviorSubject的由于源码较多这里就不贴出来了,这个类它继承了Subject<T>,那 Subject<T> 又是什么?源码如下:

public abstract class Subject<T> extends Observable<T> implements Observer<T> {
    /**
     * Returns true if the subject has any Observers.
     * <p>The method is thread-safe.
     * @return true if the subject has any Observers
     */
    public abstract boolean hasObservers();

    /**
     * Returns true if the subject has reached a terminal state through an error event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through an error event
     * @see #getThrowable()
     * @see #hasComplete()
     */
    public abstract boolean hasThrowable();

    /**
     * Returns true if the subject has reached a terminal state through a complete event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through a complete event
     * @see #hasThrowable()
     */
    public abstract boolean hasComplete();

    /**
     * Returns the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet.
     * <p>The method is thread-safe.
     * @return the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet
     */
    @Nullable
    public abstract Throwable getThrowable();

    /**
     * Wraps this Subject and serializes the calls to the onSubscribe, onNext, onError and
     * onComplete methods, making them thread-safe.
     * <p>The method is thread-safe.
     * @return the wrapped and serialized subject
     */
    @NonNull
    public final Subject<T> toSerialized() {
        if (this instanceof SerializedSubject) {
            return this;
        }
        return new SerializedSubject<T>(this);
    }
}

哦,上帝,Subject继承了Observable、又实现了Observer接口,这也就说明Subject即可作为被观察者,也可以作为观察者。同理,他的子类BehaviorSubject也具备同样的功能。
下面是关于BehaviorSubject操作符的一张图:


img_8f8a946e7530478bfbf83ef83e855c1a.png
BehaviorSubject

BehaviorSubject的简单理解就是,发送离订阅最近的上一个值,没有上一个值的时候会发送默认值,接下来(如果有数据)则继续发射原始Observable的数据。

2:bindUntilEvent( ActivityEvent event) 、LifecycleTransformer、takeUntil

在RxAppCompatActivity 源码中我们看到了bindUntilEvent()这个方法,最终的的返回值类型是 LifecycleTransformer 那这个LifecycleTransformer又是什么?

public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
                                                      FlowableTransformer<T, T>,
                                                      SingleTransformer<T, T>,
                                                      MaybeTransformer<T, T>,
                                                      CompletableTransformer
{
    final Observable<?> observable;

    LifecycleTransformer(Observable<?> observable) {
        checkNotNull(observable, "observable == null");
        this.observable = observable;
    }

    @Override
    public ObservableSource<T> apply(Observable<T> upstream) {
        return upstream.takeUntil(observable);
    }
  //......
}

经过源码可以发现,这个LifecycleTransformer实现了大量的XXXTransformer,内部的方法大都使用了apply方法,这个方法实则是调用了takeUntil操作符,那么这个takeUntil操作符是什么意思?

img_8aef6573397eef1c46536fb0e9cb5b85.png
takeUntil

takeUntil操作符简单理解就是,当第二个Observable发射了一项数据或者终止时,丢弃原Observable发射的任何数据。注意:这里是满足条件丢弃任何发送的数据(该操作符的应用场景是不是,在onDestroy( )里面取消订阅,解决内存泄漏的隐患)

3:bindToLifecycle()

我们知道,绑定的API是bindToLifecycle()这一行代码,那么我们就抽丝剥茧,根据RxAppCompatActivity源码得知,bindToLifecycle()这行代码最终返回了 RxLifecycleAndroid.bindActivity(lifecycleSubject),源码跟进,进入到了RxLifecycleAndroid,下面是 RxLifecycleAndroid 源码:

public class RxLifecycleAndroid {

    private RxLifecycleAndroid() {
        throw new AssertionError("No instances");
    }

    /**
     * Binds the given source to an Activity lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. In the case that the lifecycle sequence is in the
     * creation phase (CREATE, START, etc) it will choose the equivalent destructive phase (DESTROY,
     * STOP, etc). If used in the destructive phase, the notifications will cease at the next event;
     * for example, if used in PAUSE, it will unsubscribe in STOP.
     * <p>
     * Due to the differences between the Activity and Fragment lifecycles, this method should only
     * be used for an Activity lifecycle.
     *
     * @param lifecycle the lifecycle sequence of an Activity
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Activity lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindActivity(@NonNull final Observable<ActivityEvent> lifecycle) {
        return bind(lifecycle, ACTIVITY_LIFECYCLE);
    }

    /**
     * Binds the given source to a Fragment lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. In the case that the lifecycle sequence is in the
     * creation phase (CREATE, START, etc) it will choose the equivalent destructive phase (DESTROY,
     * STOP, etc). If used in the destructive phase, the notifications will cease at the next event;
     * for example, if used in PAUSE, it will unsubscribe in STOP.
     * <p>
     * Due to the differences between the Activity and Fragment lifecycles, this method should only
     * be used for a Fragment lifecycle.
     *
     * @param lifecycle the lifecycle sequence of a Fragment
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Fragment lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindFragment(@NonNull final Observable<FragmentEvent> lifecycle) {
        return bind(lifecycle, FRAGMENT_LIFECYCLE);
    }

    /**
     * Binds the given source to a View lifecycle.
     * <p>
     * Specifically, when the View detaches from the window, the sequence will be completed.
     * <p>
     * Warning: you should make sure to use the returned Transformer on the main thread,
     * since we're binding to a View (which only allows binding on the main thread).
     *
     * @param view the view to bind the source sequence to
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the View lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindView(@NonNull final View view) {
        checkNotNull(view, "view == null");

        return bind(Observable.create(new ViewDetachesOnSubscribe(view)));
    }

    // Figures out which corresponding next lifecycle event in which to unsubscribe, for Activities
    private static final Function<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE =
        new Function<ActivityEvent, ActivityEvent>() {
            @Override
            public ActivityEvent apply(ActivityEvent lastEvent) throws Exception {
                switch (lastEvent) {
                    case CREATE:
                        return ActivityEvent.DESTROY;
                    case START:
                        return ActivityEvent.STOP;
                    case RESUME:
                        return ActivityEvent.PAUSE;
                    case PAUSE:
                        return ActivityEvent.STOP;
                    case STOP:
                        return ActivityEvent.DESTROY;
                    case DESTROY:
                        throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
                    default:
                        throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
                }
            }
        };

    // Figures out which corresponding next lifecycle event in which to unsubscribe, for Fragments
    private static final Function<FragmentEvent, FragmentEvent> FRAGMENT_LIFECYCLE =
        new Function<FragmentEvent, FragmentEvent>() {
            @Override
            public FragmentEvent apply(FragmentEvent lastEvent) throws Exception {
                switch (lastEvent) {
                    case ATTACH:
                        return FragmentEvent.DETACH;
                    case CREATE:
                        return FragmentEvent.DESTROY;
                    case CREATE_VIEW:
                        return FragmentEvent.DESTROY_VIEW;
                    case START:
                        return FragmentEvent.STOP;
                    case RESUME:
                        return FragmentEvent.PAUSE;
                    case PAUSE:
                        return FragmentEvent.STOP;
                    case STOP:
                        return FragmentEvent.DESTROY_VIEW;
                    case DESTROY_VIEW:
                        return FragmentEvent.DESTROY;
                    case DESTROY:
                        return FragmentEvent.DETACH;
                    case DETACH:
                        throw new OutsideLifecycleException("Cannot bind to Fragment lifecycle when outside of it.");
                    default:
                        throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
                }
            }
        };

}

嗯,首先看到bindActivity(final Observable<ActivityEvent> lifecycle)这个方法,这个方法最终返回了bind(lifecycle, ACTIVITY_LIFECYCLE);

请注意,前方高能: ACTIVITY_LIFECYCLE,这个ACTIVITY_LIFECYCLE的源码也是上面的截图,可以看到通过switch语句进行条件筛选最终返回ActivityEvent这个枚举里面的属性值(仔细观看的话源码下面还有Fragment对应的生命周期),可能你会问,为什么这是对应的生命周期?让我们首先看回bind(lifecycle, ACTIVITY_LIFECYCLE); 这个方法,点进去看,进入到了 RxLifecycle 这个类,源码如下:

public class RxLifecycle {

    private RxLifecycle() {
        throw new AssertionError("No instances");
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * When the lifecycle event occurs, the source will cease to emit any notifications.
     *
     * @param lifecycle the lifecycle sequence
     * @param event the event which should conclude notifications from the source
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source at the specified event
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bindUntilEvent(@Nonnull final Observable<R> lifecycle,
                                                                @Nonnull final R event) {
        checkNotNull(lifecycle, "lifecycle == null");
        checkNotNull(event, "event == null");
        return bind(takeUntilEvent(lifecycle, event));
    }

    private static <R> Observable<R> takeUntilEvent(final Observable<R> lifecycle, final R event) {
        return lifecycle.filter(new Predicate<R>() {
            @Override
            public boolean test(R lifecycleEvent) throws Exception {
                return lifecycleEvent.equals(event);
            }
        });
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. Note that for this method, it assumes <em>any</em> event
     * emitted by the given lifecycle indicates that the lifecycle is over.
     *
     * @param lifecycle the lifecycle sequence
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source whenever the lifecycle emits
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
        return new LifecycleTransformer<>(lifecycle);
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * This method determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. It uses the provided correspondingEvents function to determine
     * when to unsubscribe.
     * <p>
     * Note that this is an advanced usage of the library and should generally be used only if you
     * really know what you're doing with a given lifecycle.
     *
     * @param lifecycle the lifecycle sequence
     * @param correspondingEvents a function which tells the source when to unsubscribe
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Fragment lifecycle
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle,
                                                      @Nonnull final Function<R, R> correspondingEvents) {
        checkNotNull(lifecycle, "lifecycle == null");
        checkNotNull(correspondingEvents, "correspondingEvents == null");
        return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
    }

    private static <R> Observable<Boolean> takeUntilCorrespondingEvent(final Observable<R> lifecycle,
                                                                       final Function<R, R> correspondingEvents) {
        return Observable.combineLatest(
            lifecycle.take(1).map(correspondingEvents),
            lifecycle.skip(1),
            new BiFunction<R, R, Boolean>() {
                @Override
                public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
                    return lifecycleEvent.equals(bindUntilEvent);
                }
            })
            .onErrorReturn(Functions.RESUME_FUNCTION)
            .filter(Functions.SHOULD_COMPLETE);
    }
}

最终执行到了 RxLifecycle 这个类源码里面的最后的两个方法!

4:takeUntilCorrespondingEvent()

takeUntilCorrespondingEvent这个方法内容较多,首先分析第一个,combineLatest操作符,这个操作符是指 将传进来的BehaviorSubject的事件进行了一次分割;假设我们现在在onCreate()方法里面进行RxLifecycle的绑定,那么这里的lifecycle.take(1).map(correspondingEvents)简单理解其对应的代码就是 RxLifecycleAndroid源码 里面的ACTIVITY_LIFECYCLE 中的,

 case CREATE:
 return ActivityEvent.DESTROY;

另外,lifecycle.skip(1)意味着除去第一个(ActivityEvent.CREATE),保留剩下的ActivityEvent枚举值

new BiFunction<R, R, Boolean>这行代码是对属性值进行判断:对比结果是
false,false,fasle,false,true

最后,onErrorReturn和filter这两行代码分别是对异常的处理以及判断是否应该结束订阅、

final class Functions {

    static final Function<Throwable, Boolean> RESUME_FUNCTION = new Function<Throwable, Boolean>() {
        @Override
        public Boolean apply(Throwable throwable) throws Exception {
            if (throwable instanceof OutsideLifecycleException) {
                return true;
            }

            //noinspection ThrowableResultOfMethodCallIgnored
            Exceptions.propagate(throwable);
            return false;
        }
    };

    static final Predicate<Boolean> SHOULD_COMPLETE = new Predicate<Boolean>() {
        @Override
        public boolean test(Boolean shouldComplete) throws Exception {
            return shouldComplete;
        }
    };

    static final Function<Object, Completable> CANCEL_COMPLETABLE = new Function<Object, Completable>() {
        @Override
        public Completable apply(Object ignore) throws Exception {
            return Completable.error(new CancellationException());
        }
    };

    private Functions() {
        throw new AssertionError("No instances!");
    }
}

综上:本次订阅,当Activity走到onStart生命周期时,为false,订阅不会取消,直到onDestroy,为true,订阅取消

5:最后调用的方法

根据逻辑,上面最终调用了下面的代码:

    public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
        return new LifecycleTransformer<>(lifecycle);
    }

可以看到,这里最终生成了一个LifecycleTransformer。

源码逻辑总结:

A:继承了RxAppCompatActivity的子类Activity,在每个生命的周期里,BehaviorSubject发射相对应的事件
B:bind方法主要是做赋值、匹配、判断
C:LifecycleTransformer内部进行takeUntil操作符,如果是true,就终止订阅,反之

如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

相关文章
|
20天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
40 19
|
20天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
45 14
|
21天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
在数字时代,掌握安卓应用开发技能是进入IT行业的关键。本文将引导读者从零基础开始,逐步深入安卓开发的世界,通过实际案例和代码示例,展示如何构建自己的第一个安卓应用。我们将探讨基本概念、开发工具设置、用户界面设计、数据处理以及发布应用的全过程。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你提供宝贵的知识和技能,帮助你在安卓开发的道路上迈出坚实的步伐。
31 5
|
20天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
21天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
21天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
21天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
27 0
|
缓存 安全 开发工具
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
935 0
|
Android开发
Android Studio在android Emulator中运行的项目黑屏
Android Studio在android Emulator中运行的项目黑屏
764 0
Android Studio在android Emulator中运行的项目黑屏
|
Android开发 开发者 Windows
Android Studio运行项目
一、在真机上运行(Mac没得) 二、Android Studio自带模拟器(AVD)安装以及运行项目 三、在模拟器上运行
659 0
Android Studio运行项目