android网络开源框架volley(三)——请求队列是主线

使用Volley发起网络请求 前言 本文是对Google官方文档中关于Volley部分的学习和总结,原文地址详情参考,通过对文档的翻译和学习,总结出自己的理解,通过一个Demo来展现 Volley概述 Volley是一个Google推出的一个HTTP网络请求开源库,它可以简化Android应用程序的联网操作,以更快的速度进行网络请求,很多大公司的App都集成了Volley库。 Volley开源库具有的优点包括: 自动进行网络... 阅读详情

忽忽,很意外,第二篇大家反映还不错哈,谢谢咯~~对于这篇,要写好信心不大,不过我会尽量的。


1、从哪里开始:

从哪里开始,菜鸟能想到的当然是从最先接触的地方开始啦~~ 

首先我们看volley.java这个类:

    /**
     * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
     *
     * @param context A {@link Context} to use for creating the cache dir.
     * @param stack An {@link HttpStack} to use for the network, or null for default.
     * @return A started {@link RequestQueue} instance.
     */
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);

        String userAgent = "volley/0";
        try {
            String packageName = context.getPackageName();
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException e) {
        }

        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        Network network = new BasicNetwork(stack);

        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();

        return queue;
    }
回忆下之前我们就是通过它拿到我们的请求队列,在对newRequestQueue的描述中我们也得到验证:创建一个工作池(带优先级的阻塞队列)的实例。在这里有两个静态的构造方法,除去我们之前使用过的,另一个多了一个参数HttpStack(HttpStack稍后分析)。而我们之前并没有使用这个带HttpStack的构造方法。因此就有了上面对stack==null的判断:根据不同的版本创建不同的实例。判断的原因注释中也写的很明确: Gingerbread(2.3)之前,HttpUrlConnection不可用。这里就很自然的想到这样一个问题:Gingerbread(2.3)之前和之后的版本在网络请求上有何区别(或者HTTP Client与HttpURLConnection的区别)?如果 那个网页你打不开,可以在这里 下载英文原版,或者 去看大牛翻译好的。完成HttpStack的创建之后紧接着有创建了一个Network和RequestQueue对象:Network执行网络请求;RequestQueue是A request dispatch queue with a thread pool of dispatchers。下面我们将围绕着RequestQueue进行展开。对了,还有一个HttpStack接口,只有一个方法,这里简单提一下:

public interface HttpStack {
    /**
     * Performs an HTTP request with the given parameters.
     *
     * <p>A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise,
     * and the Content-Type header is set to request.getPostBodyContentType().</p>
     *
     * @param request the request to perform
     * @param additionalHeaders additional headers to be sent together with
     *         {@link Request#getHeaders()}
     * @return the HTTP response
     */
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
        throws IOException, AuthFailureError;

}
使用给定的参数执行HTTP请求。通过上面的判断我们知道它有两个实现类:HurlStack和HttpClientStack。这样我们就得到下面的一个关系图:

这样他们的关系就相当明了了。


2、请求队列:RequestQueue

直接看关键构造函数:
   /**
     * Creates the worker pool. Processing will not begin until {@link #start()} is called.
     *
     * @param cache A Cache to use for persisting responses to disk
     * @param network A Network interface for performing HTTP requests
     * @param threadPoolSize Number of network dispatcher threads to create
     * @param delivery A ResponseDelivery interface for posting responses and errors
     */
    public RequestQueue(Cache cache, Network network, int threadPoolSize,
            ResponseDelivery delivery) {
        mCache = cache;
        mNetwork = network;
        mDispatchers = new NetworkDispatcher[threadPoolSize];
        mDelivery = delivery;
    }
这里我们传入了一个cache、Network、线程池大小和传递响应的对象。默认的线程池大小是4。创建这个RequestQueue对象之后,我们需要调用它的start()方法,完成对调度器的初始化工作,如根据传入线程池大小创建相应数量的Dispatcher(这里我们暂时只关注网络处理线程),然后启动:
    /**
     * Starts the dispatchers in this queue.
     */
    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }
NetworkDispatcher的构造函数中传入了一个mNetworkQueue对象,这是一个带优先级的阻塞队列:
/** The queue of requests that are actually going out to the network. */
private final PriorityBlockingQueue<Request> mNetworkQueue = new PriorityBlockingQueue<Request>();
另一个需要关注的就是add方法:
/**
     * Adds a Request to the dispatch queue.
     * @param request The request to service
     * @return The passed-in request
     */
    public Request add(Request request) {
        // Tag the request as belonging to this queue and add it to the set of current requests.
        request.setRequestQueue(this);
        synchronized (mCurrentRequests) {
            mCurrentRequests.add(request);
        }

        // Process requests in the order they are added.
        request.setSequence(getSequenceNumber());
        request.addMarker("add-to-queue");

        // If the request is uncacheable, skip the cache queue and go straight to the network.
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }

        // Insert request into stage if there's already a request with the same cache key in flight.
        synchronized (mWaitingRequests) {
            String cacheKey = request.getCacheKey();
            if (mWaitingRequests.containsKey(cacheKey)) {
                // There is already a request in flight. Queue up.
                Queue<Request> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new LinkedList<Request>();
                }
                stagedRequests.add(request);
                mWaitingRequests.put(cacheKey, stagedRequests);
                if (VolleyLog.DEBUG) {
                    VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
                }
            } else {
                // Insert 'null' queue for this cacheKey, indicating there is now a request in
                // flight.
                mWaitingRequests.put(cacheKey, null);
                mCacheQueue.add(request);
            }
            return request;
        }
    }
通过上面的代码我们可以看出,volley是将我们创建的Request对象直接加到上面的mNetworkQueue中。这样我们很自然的联想到,对request的处理应该是由start中创建的NetworkDispatcher完成的。NetworkDispatcher继承了Thread,run()方法是这样实现的:
 public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        Request request;
        while (true) {
            try {
                // Take a request from the queue.
                request = mQueue.take();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            }

            try {
                request.addMarker("network-queue-take");

                // If the request was cancelled already, do not perform the
                // network request.
                if (request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                    continue;
                }

                // Tag the request (if API >= 14)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
                }

                // Perform the network request.
                NetworkResponse networkResponse = mNetwork.performRequest(request);
                request.addMarker("network-http-complete");

                // If the server returned 304 AND we delivered a response already,
                // we're done -- don't deliver a second identical response.
                if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                    request.finish("not-modified");
                    continue;
                }

                // Parse the response here on the worker thread.
                Response<?> response = request.parseNetworkResponse(networkResponse);
                request.addMarker("network-parse-complete");

                // Write to cache if applicable.
                // TODO: Only update cache metadata instead of entire record for 304s.
                if (request.shouldCache() && response.cacheEntry != null) {
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }

                // Post the response back.
                request.markDelivered();
                mDelivery.postResponse(request, response);
            } catch (VolleyError volleyError) {
                parseAndDeliverNetworkError(request, volleyError);
            } catch (Exception e) {
                VolleyLog.e(e, "Unhandled exception %s", e.toString());
                mDelivery.postError(request, new VolleyError(e));
            }
        }
    }
首先从请求队列中取出一个请求;然后通过Network开始执行这个request请求,这个时候会拿到请求返回的结果;接着把请求的结果返给request进行处理:
Response<?> response = request.parseNetworkResponse(networkResponse);
request处理之后会返回一个response,这个response和request最后会传递到ResponseDeliveryRunnable中处理:
   /**
     * A Runnable used for delivering network responses to a listener on the
     * main thread.
     */
    @SuppressWarnings("rawtypes")
    private class ResponseDeliveryRunnable implements Runnable {
        private final Request mRequest;
        private final Response mResponse;
        private final Runnable mRunnable;

        public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
            mRequest = request;
            mResponse = response;
            mRunnable = runnable;
        }

        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            // If this request has canceled, finish it and don't deliver.
            if (mRequest.isCanceled()) {
                mRequest.finish("canceled-at-delivery");
                return;
            }

            // Deliver a normal response or error, depending.
            if (mResponse.isSuccess()) {
                mRequest.deliverResponse(mResponse.result);
            } else {
                mRequest.deliverError(mResponse.error);
            }

            // If this is an intermediate response, add a marker, otherwise we're done
            // and the request can be finished.
            if (mResponse.intermediate) {
                mRequest.addMarker("intermediate-response");
            } else {
                mRequest.finish("done");
            }

            // If we have been provided a post-delivery runnable, run it.
            if (mRunnable != null) {
                mRunnable.run();
            }
       }
    }
这里我们可以看到,如果请求的响应是成功的,会去调用request的deliverResponse,这样一个完整的请求响应过程就完成了。
细心的你可能已经发现,从RequestQueue的add()方法开始,到NetworkDispatcher的run()方法结束,很多地方调用了request.addMarker("**-**-**");这个方法,通过里面的字符串,我们可以方便的理解整个处理流程:add-to-queue、network-queue-take、network-http-complete、network-parse-complete、network-cache-written、post-response/post-error、intermediate-response,另外还有request.finish("***-***");这个也可以帮助我们理解整个处理流程。

如上图(这个图我想修改下,但是不知道怎么改,都是拖出来的)。

3、请求的细节

从NetworkDispatcher的run()开始(代码上方有贴)。

3.1 第一次取消

                request.addMarker("network-queue-take");

                // If the request was cancelled already, do not perform the
                // network request.
                if (request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                    continue;
                }
此时状态是刚从队列中取出:network-queue-take。首先,判断此请求是否已经取消,若取消直接调用request的finish()方法。这个时候我们会想到,怎么知道已经取消,或者用户怎么取消请求呢?到request中我们可以找到一个cancel()方法,就是通过此方法来取消请求的。注销 这个方法,我们可以看到在RequestQueue中有调用此方法,它们是:
    /**
     * Cancels all requests in this queue for which the given filter applies.
     * @param filter The filtering function to use
     */
    public void cancelAll(RequestFilter filter) {
        synchronized (mCurrentRequests) {
            for (Request<?> request : mCurrentRequests) {
                if (filter.apply(request)) {
                    request.cancel();
                }
            }
        }
    }

    /**
     * Cancels all requests in this queue with the given tag. Tag must be non-null
     * and equality is by identity.
     */
    public void cancelAll(final Object tag) {
        if (tag == null) {
            throw new IllegalArgumentException("Cannot cancelAll with a null tag");
        }
        cancelAll(new RequestFilter() {
            @Override
            public boolean apply(Request<?> request) {
                return request.getTag() == tag;
            }
        });
    }
这样,我们就可以知道,取消一个请求可以通过RequestQueue中的cancelAll()方法进行。这个时候取消的话,我们的请求是不会发出去的。当然,取消在任何时候都会发生,下面还会讲到,请求返回后取消的话结果是不会传递给用户的。

3.2 发起网络请求

                // Perform the network request.
                NetworkResponse networkResponse = mNetwork.performRequest(request);
                request.addMarker("network-http-complete");
通过执行network的performRequest()方法拿到一个请求结果。执行完这个时候,我们就得到了请求的结果。此处是可以自定义的,我们看下默认实现:
    @Override
    public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();
        while (true) {
            HttpResponse httpResponse = null;
            byte[] responseContents = null;
            Map<String, String> responseHeaders = new HashMap<String, String>();
            try {
                // Gather headers.
                Map<String, String> headers = new HashMap<String, String>();
                addCacheHeaders(headers, request.getCacheEntry());
                httpResponse = mHttpStack.performRequest(request, headers);
                StatusLine statusLine = httpResponse.getStatusLine();
                int statusCode = statusLine.getStatusCode();

                responseHeaders = convertHeaders(httpResponse.getAllHeaders());
                // Handle cache validation.
                if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                            request.getCacheEntry().data, responseHeaders, true);
                }

                // Some responses such as 204s do not have content.  We must check.
                if (httpResponse.getEntity() != null) {
                  responseContents = entityToBytes(httpResponse.getEntity());
                } else {
                  // Add 0 byte response as a way of honestly representing a
                  // no-content request.
                  responseContents = new byte[0];
                }

                // if the request is slow, log it.
                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                logSlowRequests(requestLifetime, request, responseContents, statusLine);

                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }
                return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
            } catch (SocketTimeoutException e) {
                attemptRetryOnException("socket", request, new TimeoutError());
            } catch (ConnectTimeoutException e) {
                attemptRetryOnException("connection", request, new TimeoutError());
            } catch (MalformedURLException e) {
                throw new RuntimeException("Bad URL " + request.getUrl(), e);
            } catch (IOException e) {
                int statusCode = 0;
                NetworkResponse networkResponse = null;
                if (httpResponse != null) {
                    statusCode = httpResponse.getStatusLine().getStatusCode();
                } else {
                    throw new NoConnectionError(e);
                }
                VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                if (responseContents != null) {
                    networkResponse = new NetworkResponse(statusCode, responseContents,
                            responseHeaders, false);
                    if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
                            statusCode == HttpStatus.SC_FORBIDDEN) {
                        attemptRetryOnException("auth",
                                request, new AuthFailureError(networkResponse));
                    } else {
                        // TODO: Only throw ServerError for 5xx status codes.
                        throw new ServerError(networkResponse);
                    }
                } else {
                    throw new NetworkError(networkResponse);
                }
            }
        }
    }
关键部分:httpResponse = mHttpStack.performRequest(request, headers);通过这个执行网络请求。具体的细节还是可以自定义的。代码贴的太多就不继续贴了,两个实现大家可以具体去看看,比如网络请求超时时间的设置都是通过:request.getTimeoutMs();得到的。再到Request中你就可以知道设置超时是通过下面代码实现的:
/**
     * Sets the retry policy for this request.
     */
    public void setRetryPolicy(RetryPolicy retryPolicy) {
        mRetryPolicy = retryPolicy;
    }

3.3 解析请求结果

		// Parse the response here on the worker thread.
                Response<?> response = request.parseNetworkResponse(networkResponse);
                request.addMarker("network-parse-complete");
这个是不是很熟悉,我们在request中实现的parseNetworkResponse()。

3.4 最后结果的处理

这就说了,大家可以继续看默认的代码实现。值得提的是,在这里我们会发现,又一次调用了mRequest.isCanceled()决定是否将结果传递给用户。

4、总结

Volley.java 这个类的目的很明确,就是获取一个RequestQueue对象。从代码中可以看出,为了达到这个目的,我们至少要创建三个关键对象,Cache、Network、HttpStack。Cache是一个处理响应的缓存;Network是执行网络请求的接口;HttpStack是真正的执行网络请求的接口。Network和HttpStack都是接口,这样volley给我们预留了充足的自定义空间。如果完全自定义,我们可以创建自己的HttpStack和Network实现,这样我们就可以不再使用volley.java这个类了。

这篇文章写了半个月,也算完整的伴随最近的感情变迁。虽然后面写的越来越糟糕,不过现在终于写完了。欢迎各位指教~~


【学习笔记-Android】(十三) 网络篇(二)——Volley框架 + 使用Gson解析json数据 目录: 一、HttpURLConnection 二、Volley框架 + 使用Gson解析json数据 三、OkHttp3框架 + 使用Gson解析json数据 四、WebView组件 ==================================================== 学习使用Volley框架 使用步骤: 1、加入gradle依赖 // https://mvnreposito... 阅读详情

相关推荐

Android:Volley框架分析(二)——请求队列

在Android:Volley框架分析(一)——请求准备并发出的操作步骤中,我们了解了一个请求发出去的步骤,这一节我们就来看看请求队列的事。 requestQueue.add(request); 通过上面的代码,一个请求就被加入到Volley的请求队列,请求将被逐个执行。 先来看看请求队列的内部的几个属性。 mCurrentRequests:当前这个队列里面所有的请求集合(包括等待中的和...

bdmh的专栏 928

一次网络请求的完整过程

客户端的视角 用户输入URL,浏览器解析url 我们都知道,url其实是一种方便人类记忆的标识符,实际上计算机都是通过IP地址进行通信的。这个url转IP的过程就叫解析域名。 步骤一般分为下面几步: 1.利用本地host文件进行解析 2.向本地DNS服务器请求解析 3.本地DNS服务器向根DNS服务器、域服务器等请 求解析(有递归和迭代两种方式) 4.本地DNS服务器在请求完成后需要缓存url和ip的映射关系 浏览器发起连接 浏览器会先和服务器建立TCP连接(80端口),再构造http报文发送ht

晴空万里 2607

Android Volley网络库:全面使用指南

Volley是Google开发并开源的一款网络通信库,它专为Android应用设计,旨在提供一个更高效、更简洁的网络请求处理方案。Volley支持同步和异步网络操作,允许开发者发送和接收数据,尤其适用于网络请求频繁、数据量小的场景。Volley的缓存策略设计得相对简单且易于理解。Volley提供默认的缓存实现,允许开发者基于URL对网络响应进行缓存。Volley的缓存是可选的,可以根据需要开启或关闭,同时支持自定义缓存逻辑。

weixin_34945060的博客 861

Android网络框架volley学习(五)请求队列RequestQueue简析

RequestQueue:表示请求队列,查看源码得知,里面包含一个CacheDispatcher(用于处理走缓存请求的调度线程)、NetworkDispatcher数组(用于处理走网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 函数启动时会启动CacheDispatcher和NetworkDispatchers。 本篇内容我们来详细的了解一下

ostracod 3748

Android-TimeTask是一个轻量简洁的定时任务队列框架

TimeTask是一个轻量简洁的定时任务队列框架,专注处理多组任务分发工作 TimeTask内部的实现时基于AlarmManager 广播,在任务与系统api中间做了较好的封装

Android网络请求队列

博客 http://blog.youkuaiyun.com/chuwe1/article/details/49589305 源码,实现安卓网络请求队列,类似新浪微博效果

Android学习之Volley网络请求框架

请求对象:StringRequest,JsonObjectRequest,JsonAarryRequest,ImageRequest 步骤: 1.创建一个请求队列RequestQueue 2.创建Request对象 3.将请求对象添加到请求队列中 具体实现: 1.在AndroidManifest.xml中添加网络访问权限: <uses-permission android:name="android.permission.INTERNET" /> 2.在.

weixin_37879993的博客 782

Android最基本的异步网络请求框架

主要为大家详细介绍了Android最基本的异步网络请求框架,感兴趣的小伙伴们可以参考一下

终极Android网络请求指南:Retrofit与Volley深度对比及选型攻略

在Android开发中,网络请求是连接App与后端服务的核心桥梁。**Retrofit**和**Volley**作为两大主流网络框架,各自凭借独特优势占据着开发者的技术栈。本文将从架构设计、性能表现、使用场景等维度展开深度对比,助你快速掌握选型技巧,打造高效稳定的网络层。 ### 🚀 框架核心架构解析 #### Retrofit:注解驱动的类型安全方案 Retrofit由Square公司开发,

gitblog_01163的博客 1000

数字IC笔记-低功耗技术

传统的降低Power的方法主要有: 1.门控时钟技术(clock gating) 2.多阈值电压技术(MultiShreshold) 3.动态电压频率调节技术(DVFS) 目前有以下几种低功耗技术: 1.多电压技术(Multi-Voltage) 2.MTCOMS Power Gating 技术(多阈值功耗控制技术),比如基带部分中的2G、3G、CDMA、LTE等通过awake—>sleep—>awake的方式间歇式的打开或关断其电源,power gating 可以完全关掉dynamic的pow

sinat_41774721的博客 1933

Adams中AKISPL和DX函数的妙用:打造精准的非线性衬套模型

本文深入探讨了在Adams动力学软件中,如何巧妙运用AKISPL插值函数与DX等位移测量函数,构建高精度的非线性衬套模型。文章通过实战案例,详细解析了从单轴非线性刚度到完整六自由度耦合模型的实现步骤与调试技巧,帮助工程师将复杂的实验或有限元数据转化为可靠的多体动力学仿真模型,有效提升系统仿真置信度。

sky77的博客 324

Android应用开发:网络工具——Volley(一)

以Cloudant为例详细介绍Android网络请求工具Volley中StringRequest和JsonObjectRequest的使用方法。

Feed Technology 1万+

DCA决策曲线的解读和代码实现

0.决策曲线 决策曲线分析法(Decision Curve Analysis,DCA)是个与ROC曲线相提并论的相对比较新的模型评价方法。 关于它的原理,长篇大论的医学统计学知识解读实在不是我的强项,放上两个链接偷偷懒: https://www.plob.org/article/12455.html https://www.iikx.com/news/statistics/1622.html 如果想看文章,这篇里的fig7就是:https://www.ncbi.nlm.nih.gov/pmc/artic

weixin_42960896的博客 1万+

Android开源框架分析0——Volley框架详解

这两天花时间看了下Volley的源码,参考了几篇博文 Android Volley完全解析(四),带你从源码的角度理解Volley,Volley 源码解析,谷歌Volley网络框架讲解——网络枢纽等,有一点自己小小的心得体会,在此写出来和大家分析。1.基本网络请求操作封装既然是网络框架,最重要的当是网络请求相关操作的处理,在没有网络请求框架的时候,我们是利用最基本的HttpClient和HttpUR

Kerwin的学习历程 469

Android BluetoothSocket

BluetoothSocket是Android中用于在蓝牙设备之间进行数据传输的一种Socket。它提供了一种类似于TCP/IP协议的数据传输方式,可以在两个设备之间建立一个虚拟的通信管道,使得两个设备之间可以进行数据的传输和接收。BluetoothSocket可以用于客户端和服务端之间的通信,通过BluetoothSocket可以实现数据的双向传输。

liuning1985622的博客 1478

蓝牙EDR模式中GFSK调制如何过渡到DPSK调制

这两份文档片段揭示了蓝牙Modem设计中非常精深的部分。它的核心思想是:通过精心的脉冲形状设计和重叠,来保证幅度连续;通过在保护间隔内执行一套复杂的“相位平滑算法”(重复、斜率保持、寻找基准点、冻结),来保证相位连续。Figure 3-2 则是将这个思想用图形化的方式展现出来,说明了脉冲在时间轴上的对齐和叠加关系。这种设计确保了发射机能够严格符合蓝牙规范的要求,实现不同调制方式之间的平滑、无毛刺切换,从而保障了通信的可靠性和高效的频谱利用率。

m0_49540263的博客 283

【安卓网络请求开源框架Volley源码解析系列】定制自己的Request请求及Volley框架源码剖析...

通过前面的学习我们已经掌握了Volley的基本用法,没看过的建议大家先去阅读我的博文【安卓网络请求开源框架Volley源码解析系列】初识Volley及其基本用法。如StringRequest用来请求一段文本信息,JsonRequest(JsonObjectRequest、JsonArrayRe...

chicaochan5767的博客 190

智能硬件产品:做好一款电子硬件产品,工具必不可少

上到战略规划,中至运营策略,下至人性洞察,。最初做产品时,笔者从一开始就陷入到了对工具的痴迷,包括:PS、AutoCAD、PROE、犀牛、Axure、Keyshot、Altium……大概将 2 个多月的时间和精力都消耗在了学习使用工具上。通过工具的运用也确实提高了工作效率,在仅有创意的前提下通过灵活运用工具,一年内便成功申请了多个实用新型专利、设计了多款产品的高保真原型图等。正在上传…重新上传取消。

产品线负责人 1445

简析Android网络请求Volley框架的工作原理

Volley网络模块以及错误重试机制分析 相关类如下: Network :封装网络请求接口 BaseNetWork : Network 接口实现类,用于封装网络请求,并且对请求结果封装,且实现网络请求错误重试机制。 HttpStack:执行网络请求接口 HurlStack:HttpStack 接口实现类,用于真正执行网络请求,并且得到请求结果。 HttpClientStack:Http

废墟的树的专栏 4179

2-1 AUTOSAR ASW概述

应用软件层(Application Software Layer,ASW)位于AUTOSAR整个架构的顶层。它由各种AUTOSAR Software Component(SW-C)组成,每个SW-C封装了各种应用的功能集。每个SW-C只能运行在一个ECU中。ASW层的设计目标是实现功能的可重用性和可配置性。它通过封装底层提供的服务,为上层应用层提供统一的接口。ASW层的开发可以基于AUTOSAR提供的标准化软件组件,也可以根据具体需求进行定制开发。

qq_42357877的博客 1906

人工智能算法面试大总结-总目录

涉及秋招、春招、社招

啥都生的博客 2万+

Android常用框架----网络请求系列框架

趁着这段时间不忙,放下工作,静下心来对Android中常用的第三方框架进行了剖析并整理,接下来从网络框架开始。 常用网络框架对比:1.okhttpokhttp和HttpClient、HttpURLConnection或Apache的HttpClient是同等级别的,他们是网络客户端,不仅Android能用,Java也能用,所以在android中想要用要进行封装以提供简单的API使用。Square 公

SiwenYY的博客 2097

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【开源项目13】Volley框架 以及 设置request超时时间

Volley提供了优美的框架,使android程序网络访问更容易、更快。 Volley抽象实现了底层的HTTP Client库,我们不需关注HTTP Client细节,专注于写出更加漂亮、干净的RESTful HTTP请求。 Volley请求会异步执行,不阻挡主线程。 Volley提供的功能 封装了异步的RESTful请求API 一个优雅and稳健的请求队列 一个可扩展的架构,使开

Geek马走日 540

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android网络框架

从代码学习Android网络框架 代码开源地址: https://github.com/hehonghui/simple_net_framework 作者博客地址: http://blog.youkuaiyun.com/column/details/simple-net.html SimpleNet网络框架 SimpleNet是一个简单的Android网络框架,该框架的结构类似Volley,该框

chenqianleo的博客 626

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Android网络编程(七) 之 Volley原理分析

1 前言 Volley是Goole在2013年Google I/O大会上推出的开源网络通信框架。Volley 的特点是使用简单而且适合数据量小,通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,它的表现就会非常糟糕,因为Volley在解析期间将所有响应保存在内存中。Volley带给我们开发者的是便利,它把Http所有通信细节、线程处理全部封装在内部,我们只需要简单调用就可以完成通信...

子云心的博客 2753

Android网络通信必备神器Volley详解——初识Volley

简介 Volley是Google开发和维护的一个网络通信开源库,具有方便、并发、快速的特点。但是Volley并不适合大文件下载或者流操作,因为在解析数据的时候Volley是把所有的response都放在内存里的。对于大文件下载可以用DownloadManager。 下载Volley 使用git下载 git clone https://android.googlesource.com

SparkYuan 1500
上一篇: android网络开源框架volley(二)——自定义你的请求对象
下一篇: RadioButton 左侧显示文字,右侧显示按钮时文字不靠边的问题解决
ttdevs
博客等级 码龄15年 388粉丝 91原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值