当前位置: 首页 > news >正文

镇江百度送网站网站建设联

镇江百度送网站,网站建设联,网店营销策划方案,wordpress浮动小人插件简介 RxJava 是一个基于 Java 的响应式编程库#xff0c;用于处理异步事件流和数据流。它是由 Netflix 开发并开源#xff0c;现在广泛用于 Android 和 Java 后端开发。RxJava 提供了一种用于组合和处理异步数据的丰富工具集#xff0c;它的核心思想是将数据流视为一系列事…简介 RxJava 是一个基于 Java 的响应式编程库用于处理异步事件流和数据流。它是由 Netflix 开发并开源现在广泛用于 Android 和 Java 后端开发。RxJava 提供了一种用于组合和处理异步数据的丰富工具集它的核心思想是将数据流视为一系列事件以响应事件的方式进行处理。RxJava 提供了丰富的操作符用于处理和转换数据流。这些操作符可以帮助你执行各种操作包括过滤、映射、合并、变换等以便更好地处理异步数据流。 RxJava 原理 Observable 和 ObserverRxJava 的核心是 Observable可观察对象和 Observer观察者。Observable 表示一个可观察的数据源它可以发射数据项而 Observer 用于订阅并监听这些数据项的变化。操作符RxJava 提供了各种操作符用于对数据流进行转换、过滤、组合和其他处理。操作符可以将一个 Observable 转换成另一个 Observable从而实现数据的转换和处理。流式编程RxJava 支持链式调用可以将多个操作符和观察者方法连接在一起以创建复杂的数据流处理逻辑。异步和线程控制RxJava 允许你轻松处理异步操作使用 subscribeOn 和 observeOn 等操作符可以指定在哪个线程上执行 Observable 和 Observer 的代码。背压处理RxJava 2 引入了背压处理机制允许 Observable 控制发射的速度以避免内存溢出和资源泄漏问题。 RxJava 在 Android 中的功能作用 简化异步操作RxJava 简化了异步操作例如网络请求、数据库访问、文件读写等。你可以使用 Observable 发射异步事件然后使用 Observer 来处理这些事件。响应式UIRxJava 可以在 Android UI 线程和后台线程之间建立响应式的通信以便在 UI 上更新数据或执行操作。处理多个观察者RxJava 允许你轻松地将多个观察者订阅到一个 Observable这对于多个界面元素依赖于相同数据源的情况很有用。处理错误和异常RxJava 提供了各种操作符用于处理错误和异常例如 onErrorReturn、onErrorResumeNext 等以确保应用程序能够更健壮地处理异常情况。组合和转换数据流RxJava 提供了丰富的操作符用于组合和转换数据流。例如你可以使用 zip 将多个数据流合并或使用 map 转换数据项的类型。事件总线RxJava 可以用作事件总线允许不同组件之间进行松散耦合的通信例如通过 RxBus 发送和接收事件。自动管理资源RxJava 可以帮助你管理资源例如自动释放订阅避免内存泄漏。测试支持RxJava 提供了测试支持可以轻松地测试异步操作确保应用程序的可靠性。 Rxjava 基本组成 1. 响应式编程 RxJava 的核心思想是响应式编程它允许你以一种响应事件的方式来处理数据流。你可以订阅一个数据流然后定义事件处理的方式。当数据项到达时它们会触发事件观察者Observer会监听这些事件并执行相应的操作。 2. 基本组件 RxJava 的基本组件包括以下几个部分 Observable可观察对象 表示一个能够发射数据项的数据源。Observable 可以发射零个或多个数据项以及错误或完成事件。Observer观察者 订阅 Observable 并监听发射的事件。Observer 可以处理数据项、错误和完成事件。Flowable (背压可观察对象) 和Observable使用和功能类似区别是Flowable支持背压Flowable操作符默认的缓存空间大小128。Subscriber订阅者 类似于 Observer用于订阅 Observable。Operator操作符 用于对 Observable 发射的数据流进行变换、过滤、合并等操作。Schedulers调度器 用于控制事件的执行线程例如在主线程或后台线程执行。 3. 操作符 RxJava 提供了大量的操作符用于操作和转换数据流。这些操作符包括 map、filter、flatMap、zip、merge 等允许你根据需要执行各种操作。 4. 异步和并发 RxJava 简化了异步编程允许你轻松地处理多线程和并发操作。你可以使用 subscribeOn 和 observeOn 操作符来指定代码的执行线程以避免阻塞主线程。 5. 错误处理 RxJava 提供了多种方式来处理错误包括 onError、onErrorReturn、onErrorResumeNext 等以确保应用程序能够更健壮地处理异常情况。 6. 背压处理 RxJava 2 引入了背压处理机制用于处理生产者和消费者之间的速率不匹配问题。背压机制允许 Observable 控制数据的发射速率以避免内存溢出和资源泄漏。 7. 在 Android 中的应用 RxJava 在 Android 开发中广泛应用于处理异步操作例如网络请求、数据库访问、UI事件响应等。它简化了异步编程提高了代码的可读性和可维护性同时提供了更好的性能和响应性。 8. 流式编程 RxJava 支持链式调用可以将多个操作符和观察者方法连接在一起以创建复杂的数据流处理逻辑。这使得代码更具表达力和可读性。 Rxjava使用 RxJava 的基本用法 \ 创建一个 Observable它会发射整数数据。\创建一个观察者 Observer用于订阅这个 Observable。使用 subscribe 方法将观察者订阅到 Observable 上观察者会监听 Observable 发射的数据项和事件。 //创建一个 Observable它会发射整数数据。val observable Observable.create(ObservableOnSubscribeInt {for (i in 1..10) {it.onNext(i)}it.onComplete()})var num: Int;var dd : Disposable? null//创建一个观察者 Observer用于订阅这个 Observableval observer object:ObserverInt{override fun onSubscribe(d: Disposable) {//当调用订阅时调用此方法dd d}override fun onNext(t: Int) {//上游发送数据时调用此方法 即当 Observable 发射数据项时调用num tif (num 5){dd!!.dispose()}Log.d(TAG,接受上游数据$t)}override fun onError(e: Throwable) {// 当出现错误时调用}override fun onComplete() {// 当 Observable 完成时调用}}//使用subscribe方法将观察者订阅到 Observable上观察者会监听Observable发射的数据项和事件。observable.subscribe(observer)也可以使用方法直接使用函数式编程把创建后的被观察者通过订阅方法订阅操作符把创建观察者作为订阅方法的参数伪代码 Observable.create(ObservableOnSubscribeInt {//上游发送数据it.onNext(1)it.onNext(3)it.onNext(5)it.onComplete()}).subscribe(object :ObserverInt{override fun onSubscribe(d: Disposable) {}override fun onNext(t: Int) {//下游接受数据Log.i(TAG,接受到上游数据$t)}override fun onError(e: Throwable) {}override fun onComplete() {}})操作符 Rxjava 的使用核心点就是各种操作符的使用所以以下介绍一些常用的 RxJava 操作符的详细使用示例 首先操作符的分类 创建操作符 just创建一个发射指定数据项的 Observable。fromArray从一个数组或可迭代对象中创建一个 Observable。create手动创建一个 Observable。range创建一个发射特定整数范围的 Observable。 转换操作符 map将数据项转换为另一种类型。flatMap将每个数据项映射为一个 Observable然后将这些 Observables 合并成一个数据流。concatMap类似于 flatMap但保持原始数据项的顺序。buffer将数据项分组为列表并以列表的形式发射。 过滤操作符 filter过滤掉不满足条件的数据项。distinct过滤掉重复的数据项。take仅发射前 N 个数据项。skip跳过前 N 个数据项。 组合操作符 merge合并多个 Observables 的数据流。zip将多个 Observables 的数据项按顺序一对一地合并。combineLatest将多个 Observables 最近的数据项合并成一个。 辅助操作符 subscribe用于订阅 Observable 并处理数据。observeOn指定观察者运行在特定的调度器上。subscribeOn指定 Observable 运行在特定的调度器上。debounce用于过滤数据流只保留最新的数据项。delay延迟发射数据项。 错误处理操作符 onErrorReturn在遇到错误时发射一个默认值。onErrorResumeNext在遇到错误时切换到另一个 Observable。retry在遇到错误时重试操作。 创建型操作符 创建型用于创建 Observable被观察者实例它们是构建数据流的起点上游。 1. Observable.create 这是最通用的创建型操作符。它允许你手动创建一个 Observable你需要在其中定义数据项的发射逻辑。这个操作符通常用于创建自定义的 Observable。 val observable Observable.createString { emitter -emitter.onNext(1) //手动调用发射逻辑emitter.onNext(2)emitter.onComplete()//手动调用发射完成的逻辑 }.subscribe(object :ObserverString{override fun onSubscribe(d: Disposable) {}override fun onNext(t: String) {Log.d(Rxjava ,下游接受到上游的数据 t)}override fun onError(e: Throwable) {}override fun onComplete() {}})或者使用Observer的简化版Consumer .subscribe(object :ConsumerString{override fun accept(t: String?) {Log.d(Rxjava,下游接受到上游的数据$t)}}) 2. Observable.just 用于创建一个发射指定数据项的 Observable。它可以发射多个数据项然后自动完成发射数据项。 val observable Observable.just(1, 3, 5,7)//just方法参数为可变参数参数类型为泛型 .subscribe(object :ConsumerString{override fun accept(t: Int) {Log.d(Rxjava,下游接受到上游的数据$t)}})3. Observable.fromArray 从一个数组、可迭代对象或可变参数列表中创建一个 Observable。然后自动完成发射数据项。 val numbers arrayOf(1, 2, 3) val observable Observable.fromArray(numbers) .subscribe(object :ConsumerArrayInt{override fun accept(t: ArrayInt?) {}})4. Observable.fromIterable 从一个 Iterable 对象如 List 或 Set中创建一个 Observable。 val list listOf(A, B, C)val observable Observable.fromIterable(list).subscribe(object :ConsumerString{override fun accept(t: String?) {}}) 5. Observable.interval 创建一个 Observable定期发射一个递增的长整型数值。 Observable.interval(1, TimeUnit.SECONDS)//重载方法很多 .subscribe(object :ConsumerLong{ override fun accept(t: Long?) {}})6. Observable.range 创建一个 Observable发射一个指定范围内的整数序列。 Observable.range(1,6).subscribe(object :ConsumerInt{override fun accept(t: Int?) {}})7. Observable.timer 创建一个 Observable在指定延迟后发射一个数据项。 Observable.timer(2, TimeUnit.SECONDS).subscribe(object :ConsumerLong{override fun accept(t: Long?) {}})这些创建型操作符用于生成不同类型的 Observable根据需求选择合适的操作符。它们是构建数据流的起点后续可以使用各种操作符对数据流进行变换、过滤、合并等操作以满足具体的需求。在实际应用中你通常会根据场景选择适当的创建型操作符来构建 Observable。 转换操作符 RxJava 的转换操作符用于对 Observable 发射的数据流进行变换、映射和操作。它们允许你以不同的方式处理数据项以满足特定需求。 map 操作符 map 用于将 Observable 发射的每个数据项转换为另一种数据类型。它的参数是一个函数该函数将原始数据项转换为新的数据项。 Observable.just(1, 2, 3).map(object :FunctionInt,String{override fun apply(t: Int?): String {val str t.toString()return str}}).subscribe(object:ConsumerString{override fun accept(t: String?) {Log.d(TAG, Transformed: $t)}})/*subscribe {value -Log.d(TAG, Transformed: $value)}*/flatMap 操作符 flatMap 用于将每个数据项映射为一个 Observable然后将这些 Observables 合并成一个单一的数据流。这允许并发处理数据项。 Observable.just(1, 2, 3).flatMap(object:FunctionInt ,ObservableString{override fun apply(t: Int?): ObservableString {return Observable.just(t.toString())}}) // flatMap { number - // Observable.just(number, number * 2) // }.subscribe { value - Log.d(TAG, FlatMapped: $value) }concatMap 操作符 concatMap 类似于 flatMap但它保持原始数据项的顺序。它等待前一个 Observable 完成后才处理下一个。 Observable.just(1, 2, 3).concatMap(object:FunctionInt ,ObservableString{override fun apply(t: Int?): ObservableString {return Observable.just(t.toString())}})/*.concatMap { number -Observable.just(number, number * 2)}*/.subscribe { value - Log.d(TAG, ConcatMapped: $value) }buffer 操作符 buffer 用于将数据项分组为列表并以列表的形式发射。你可以指定每个列表中的数据项数量。 Observable.just(1, 2, 3, 4, 5, 6).buffer(2).subscribe(object:ConsumerListInt{override fun accept(t: ListInt?) {Log.d(Rxjava,Buffered: $t)}})/*.subscribe { buffer - println(Buffered: $buffer) }*/groupBy 操作符 groupBy 允许你将 Observable 数据项按某个标准进行分组然后发射多个子 Observable每个子 Observable 包含一组具有相同标准的数据项。 Observable.just(1, 2, 3, 4, 5, 6).groupBy(object : FunctionInt, String {override fun apply(t: Int): String {if (t!! % 2 0) {return 偶数}return 奇数}}).subscribe(object : ConsumerGroupedObservableString, Int { //注意GroupedObservableString, Int参数的类型和FunctionInt, String反过来override fun accept(t: GroupedObservableString, Int) { //GroupedObservable被观察者t.subscribe(object : ConsumerInt {override fun accept(value: Int?) {Log.d(Rxjava, Group ${t.key}: ${value})}})}})//lambda表达式Observable.just(1, 2, 3, 4, 5, 6).groupBy { it % 2 0 }.subscribe { group -group.subscribe { value -Log.d(Rxjava, Group ${group.key}: $value)}}scan 操作符 scan 用于将数据项累积成一个中间结果然后发射这个中间结果。 Observable.just(1, 2, 3, 4, 5).scan(object :BiFunctionInt,Int,Int{override fun apply(t1: Int, t2: Int): Int {return t1 t2}}).subscribe(object:ConsumerInt{override fun accept(t: Int?) {Log.d(Rxjava,Scanned: $t)}}) // .scan { acc, value - acc value } // .subscribe { result - Log.d(Rxjava,Scanned: $result) }打印结果 Scanned: 1 Scanned: 3 Scanned: 6 Scanned: 10 Scanned: 15这些转换操作符可以帮助你根据需要对数据流进行变换、映射和操作。你可以选择合适的操作符来满足具体的业务需求以便更有效地处理异步数据流。 RxJava 提供了众多其他转换操作符可以根据实际需求查阅文档来使用。 过滤操作符 RxJava 的过滤操作符用于从 Observable 中过滤、筛选和筛除数据项以便只保留满足特定条件的数据项。 filter 操作符 filter 用于过滤掉不满足条件的数据项只保留满足条件的数据项。条件由一个函数决定。 Observable.just(1, 2, 3, 4, 5, 6).filter(object:PredicateInt{override fun test(t: Int): Boolean {return t%2 0;}}).subscribe(object :ConsumerInt{override fun accept(value: Int?) {Log.d(Rxjava,Filtered: $value)}})/* .filter { it % 2 0 }.subscribe { value - Log.d(Rxjava,Filtered: $value) }*/distinct 操作符 distinct 用于过滤掉重复的数据项只保留第一次出现的数据项。 //lambda写法 Observable.just(1, 2, 2, 3, 4, 4, 5).distinct().subscribe { value - println(Distinct: $value) } distinctUntilChanged 操作符 distinctUntilChanged 用于过滤掉连续重复的数据项只保留第一次出现的数据项。 //lambda写法 Observable.just(1, 1, 2, 2, 3, 4, 4, 5).distinctUntilChanged().subscribe { value - println(DistinctUntilChanged: $value) }take 操作符 take 用于仅发射前 N 个数据项忽略其余的数据项。 Observable.just(1, 2, 3, 4, 5).take(3).subscribe { value - println(Taken: $value) } skip 操作符 skip 用于跳过前 N 个数据项只发射后续的数据项。 Observable.just(1, 2, 3, 4, 5).skip(2).subscribe { value - println(Skipped: $value) } elementAt 操作符 elementAt 用于发射指定索引位置的数据项忽略其他数据项。 Observable.just(1, 2, 3, 4, 5).elementAt(2).subscribe { value - println(ElementAt: $value) }takeLast 操作符 takeLast 用于仅发射最后 N 个数据项忽略前面的数据项。 Observable.just(1, 2, 3, 4, 5).takeLast(3).subscribe { value - println(TakeLast: $value) }这些过滤操作符可以帮助你根据特定条件来过滤和筛选数据流以满足具体的需求。你可以选择合适的操作符来处理数据流从而仅保留需要的数据项而忽略其他数据项。在实际应用中过滤操作符常用于数据筛选、去重、限制数量等场景以帮助你更有效地处理异步数据流。 RxJava 还提供了其他过滤操作符可以根据实际需求查阅文档来使用。 组合操作符 RxJava 的组合操作符用于将多个 Observable 合并、组合或操作以生成新的 Observable 或数据流。 merge 操作符 merge 用于合并多个 Observables 的数据流以按照发射顺序合并它们的数据项。这意味着数据项将按照它们发射的顺序合并不考虑来源 Observable。 kotlinCopy codeval observable1 Observable.just(1, 2, 3) val observable2 Observable.just(4, 5, 6)Observable.merge(observable1, observable2).subscribe { value - println(Merged: $value) } concat 操作符 concat 用于合并多个 Observables 的数据流但它保持原始 Observables 的顺序先合并第一个 Observable 的数据再合并第二个 Observable 的数据以此类推。 kotlinCopy codeval observable1 Observable.just(1, 2, 3) val observable2 Observable.just(4, 5, 6)Observable.concat(observable1, observable2).subscribe { value - println(Concatenated: $value) } zip 操作符 zip 用于将多个 Observables 的数据项一对一地合并生成一个新的 Observable。它会按顺序将每个 Observable 的相同索引位置的数据项合并在一起。 kotlinCopy codeval observable1 Observable.just(A, B, C) val observable2 Observable.just(1, 2, 3)Observable.zip(observable1, observable2) { str, num - $str$num }.subscribe { value - println(Zipped: $value) } combineLatest 操作符 combineLatest 用于将多个 Observables 最近的数据项合并成一个新的 Observable。每当任何一个源 Observable 发射新数据将使用最近发射的数据项来组合生成新的数据项。 kotlinCopy codeval observable1 Observable.interval(300, TimeUnit.MILLISECONDS).map { A$it } val observable2 Observable.interval(200, TimeUnit.MILLISECONDS).map { B$it }Observable.combineLatest(observable1, observable2) { a, b - $a-$b }.take(5).subscribe { value - println(Combined: $value) } switchOnNext 操作符 switchOnNext 用于在一个 Observable 发射多个 Observables 时切换到最新的 Observable 并发射它的数据。 kotlinCopy codeval observables listOf(Observable.just(1, 2, 3),Observable.just(4, 5, 6),Observable.just(7, 8, 9) )Observable.fromIterable(observables).switchMap { it }.subscribe { value - println(Switched: $value) } 这些组合操作符允许你将多个 Observables 合并、组合或操作以满足不同的数据处理需求。你可以根据具体的场景选择合适的操作符以便有效地处理异步数据流。在实际应用中组合操作符常用于合并多个数据源进行数据计算和处理以及管理多个数据流的交互。 RxJava 还提供了其他组合操作符可以根据实际需求查阅文档来使用。 错误操作符 RxJava 的错误处理操作符用于处理 Observable 中可能出现的错误和异常情况以确保应用程序能够更健壮地处理这些问题。 onErrorReturn 操作符 onErrorReturn 用于在 Observable 遇到错误时发射一个默认值并继续正常的数据流。 kotlinCopy codeObservable.createInt { emitter -emitter.onNext(1)emitter.onError(Exception(An error occurred)) } .onErrorReturn { error - 0 } .subscribe({ value - println(Received: $value) },{ error - println(Error: ${error.message}) } ) onErrorResumeNext 操作符 onErrorResumeNext 用于在 Observable 遇到错误时切换到另一个 Observable并继续发射数据。 kotlinCopy codeval sourceObservable Observable.createInt { emitter -emitter.onNext(1)emitter.onError(Exception(An error occurred)) }val fallbackObservable Observable.just(2, 3, 4)sourceObservable.onErrorResumeNext(fallbackObservable).subscribe({ value - println(Received: $value) },{ error - println(Error: ${error.message}) }) retry 操作符 retry 用于在 Observable 遇到错误时重试操作指定重试次数。如果重试次数用尽仍有错误错误会传递给观察者。 kotlinCopy codevar attempts 0Observable.createInt { emitter -if (attempts 3) {attemptsemitter.onError(Exception(An error occurred))} else {emitter.onNext(1)emitter.onComplete()} } .retry(3) .subscribe({ value - println(Received: $value) },{ error - println(Error: ${error.message}) } ) retryWhen 操作符 retryWhen 允许你自定义错误重试策略。你可以在 retryWhen 中返回一个 Observable用于控制重试次数和时机。 kotlinCopy codevar attempts 0Observable.createInt { emitter -if (attempts 3) {attemptsemitter.onError(Exception(An error occurred))} else {emitter.onNext(1)emitter.onComplete()} } .retryWhen { errors -errors.flatMap { error -if (attempts 3) {Observable.timer(1, TimeUnit.SECONDS)} else {Observable.error(error)}} } .subscribe({ value - println(Received: $value) },{ error - println(Error: ${error.message}) } ) onErrorComplete 操作符 onErrorComplete 用于在 Observable 遇到错误时忽略错误不传递给观察者直接完成 Observable。 kotlinCopy codeObservable.createInt { emitter -emitter.onNext(1)emitter.onError(Exception(An error occurred)) } .onErrorComplete() .subscribe({ value - println(Received: $value) },{ error - println(Error: ${error.message}) } )这些错误处理操作符允许你在 Observable 遇到错误和异常情况时采取不同的处理策略以确保你的应用程序能够更好地应对异常情况。你可以根据具体的需求选择合适的操作符以提高应用程序的可靠性和健壮性。 RxJava 还提供了其他错误处理操作符可以根据实际需求查阅文档来使用。 总结以上都是同步操作即被观察者和观察者都是在默认线程中执行Android的主线程 其他常用操作符 subscribeOn 操作符 subscribeOn 用于指定 Observable 的创建和订阅操作运行在指定的线程。通常用于将耗时的任务移到后台线程执行以避免阻塞主线程。 kotlinCopy codeObservable.createInt { emitter -// 在 IO 线程执行任务emitter.onNext(1)emitter.onComplete() } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { value - println(Received on main thread: $value) } observeOn 操作符 observeOn 用于指定观察者Observer接收数据的线程。它允许你将数据切换到主线程以更新 UI或切换到其他线程执行特定操作。 kotlinCopy codeObservable.just(1, 2, 3).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe { value - println(Received on main thread: $value) } observeOn(io.reactivex.rxjava3.schedulers.Scheduler) 除了 Android 主线程调度器 (AndroidSchedulers.mainThread())RxJava 还提供了其他内置的调度器如 Schedulers.io()、Schedulers.computation() 等用于切换到不同的线程池执行任务。 kotlinCopy codeObservable.just(1, 2, 3).subscribeOn(Schedulers.io()).observeOn(Schedulers.computation()).subscribe { value - println(Received on computation thread: $value) } subscribeOn 和 observeOn 组合 通常你需要结合使用 subscribeOn 和 observeOn 来控制 Observable 的创建和订阅线程以及观察者接收数据的线程。 kotlinCopy codeObservable.createInt { emitter -// 在 IO 线程执行任务emitter.onNext(1)emitter.onComplete() } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { value - println(Received on main thread: $value) } doOnSubscribe 和 doOnNext 操作符 这些操作符用于在特定事件发生时执行操作例如使用 doOnSubscribe 可以在订阅发生时切换线程。 kotlinCopy codeObservable.just(1, 2, 3).doOnSubscribe { println(Subscribed on ${Thread.currentThread().name}) }.subscribeOn(Schedulers.io()).doOnNext { value - println(Processing on ${Thread.currentThread().name}: $value) }.observeOn(AndroidSchedulers.mainThread()).subscribe { value - println(Received on main thread: $value) } 这些线程切换操作符允许你在 RxJava 中灵活地控制数据流的线程调度以满足不同场景下的性能和响应需求。你可以根据具体的需求和场景来选择合适的线程切换操作符以优化应用程序的性能和用户体验。 RxJava 还提供其他线程切换操作符和自定义调度器的功能可以根据实际需求查阅文档来使用。
http://www.zqtcl.cn/news/580035/

相关文章:

  • 做网站网页的人是不是思维公司网站建设包括
  • 网站建设都包括哪些网站后台如何上传文件
  • 网站便民服务平台怎么做迁安做网站中的cms开发
  • 做外贸比较好的网站怎么把网站做的好看
  • 有没有在淘宝找人做网站被骗过的台州市环保局网站开发区
  • 公司外文网站制作河南住房和城乡建设厅网站
  • 东莞做网站公司有哪些代码网站推荐
  • 棋类游戏网站开发网站首页顶部图片尺寸
  • 工信部如何查网站备案大连网络推广广告代理
  • 网站建设基本流程心得wordpress首页截断
  • 网站包括哪些内容网站开发的相关技能
  • 百度竞价 百度流量 网站权重qq推广
  • 重庆网站建设总结WordPress简单百度站长插件
  • pc网站转换成微网站工作室推广网站
  • 嘉兴优化网站公司做水果生意去哪个网站
  • 青岛知名网站建设公司排名wordpress商场插件
  • 设计网站猪八戒自己制作logo免费生成器
  • 深圳万齐创享网站建设网站建设基本教程
  • 聊城做网站信息建设工程合同可以分为
  • 网站设计 注意做筹款的网站需要什么资质
  • 家居网站建设费用国土局网站建设经验
  • 企业网站开发教程网站建设更改
  • 违法网站怎么做安全wordpress自定义应用
  • 四平英文网站建设wordpress添加特效
  • 如何在手机上制作网站企业网站 微博模块
  • 网站内容规范网站建设建设公司哪家好
  • 深圳网站制作公司地址如何制作手机版网站
  • 深圳定制网站制作报价网络交易平台
  • 鞍山网站制作报价wordpress手机客户端端
  • 开发触屏版网站标签苏州沧浪区做网站的