精华内容
下载资源
问答
  • 在前面两篇文章中,晓东和大家一起分析了android是如何向蓝牙发送扫描命令,这篇文章我们将继续来看,蓝牙在收到扫描命令之后是如何向android...Inquiry result的意思大概就是在收到inquiryresponse时候会从contro

           在前面两篇文章中,晓东和大家一起分析了android是如何向蓝牙发送扫描命令的,这篇文章我们将继续来看,蓝牙在收到扫描命令之后是如何向android上层反馈搜索到的设备以及上层对这些搜索到的设备是如何进行进一步处理的。

    7inquiry result event的分析

             Inquiry result的意思大概就是在收到inquiryresponse的时候会从controller回应这个event上来,需要注意的是一个event可能会有多个response,并不是一个response对应一个event

             7.1 inquiry resulteventspec中的定义

        它在spec中的格式如下所示:


    其中各个参数的意思如下:

    Num_Responses:表示response的设备数目。上文我们有提到一个event是可以包含多个response的,这里就是表明究竟有多少个response的。

    BD_ADDR:这个很好理解,就是每个responsebd addr。是按照顺序存储的,每个占6byte

    Page scan repetition mode:这个其实大家也不要太关心,大概的意思就是page的时候采取的策略.他们具体的差别在于:

             R0对连接的时间要求很严格,并且pagingdevice需要有很好的clock,在这种模式下,别的连接是完全没有机会进来的。当然总的来说,他的功耗也是最大的.

             R1可以理解为连接时间要求还是很严格(和R0接近),但是设备没有足够好的蓝牙clock,就会建议使用这个模式,在这种模式下,别的设备时有机会连接上来的,当然功耗就没有R0大了,可以说他是R0R1之间的一个模式。

             R2 就是连时间要求都不是那么的严格了。其他就更不谈了,功耗当然也不是很大的。

             Reserved12这两个都是在早起的spec中才看到,v1.1之前。现在4.1都要出来了,所以我们就不用管了。

             Class of device:这个表示设备的类型。他分为主要设备类和次要设备类。其中主要设备类是其中的[12:8]位来表示,次要设备类是其中的[7:2]位来表示。


                  主要设备类表


    12

    11

    10

    9

    8

    主要设备类

    0

    0

    0

    0

    0

    其他 [Ref #2]

    0

    0

    0

    0

    1

    计算机(台式机、笔记本、PDAorganizer ....

    0

    0

    0

    1

    0

    电话(手机、无绳、支付电话、调制解调器 ...

    0

    0

    0

    1

    1

    LAN/网络接入点

    0

    0

    1

    0

    0

    音频/视频(耳机、扬声器、立体声、视频显示、VCR.....

    0

    0

    1

    0

    1

    配件(鼠标、游戏杆、键盘 .....

    0

    0

    1

    1

    0

    成像(打印、扫描仪、相机、显示 ...

    0

    0

    1

    1

    1

    可穿戴

    0

    1

    0

    0

    0

    玩具

    0

    1

    0

    0

    1

    健康

    1

    1

    1

    1

    1

    未分类:未指定设备代码

    X

    X

    X

    X

    X

    所有其他保留值

    次要设备是根据主要设备再进行判断的,我就不一一列出来了,具体可以参见蓝牙官网:https://www.bluetooth.org/zh-cn/specification/assigned-numbers/baseband

    Clock_offset:表示masterslave之间的clock的偏差,有了这个值可以加快masterslave之间page的时间。


    7.2inquiry result event具体的实现代码


    static inline void inquiry_result(int index, int plen, void *ptr)
    {
            struct dev_info *dev = &devs[index];
            //表示response的设备数目
            uint8_t num = *(uint8_t *) ptr++;
            int i;
    
            /* Skip if it is not in Inquiry state */
            //这里就是首先会检查是否在discov inq的state
            if (get_state(index) != DISCOV_INQ)
                    return;
    
            for (i = 0; i < num; i++) {
                    //inquiry info就是返回那些参数了
                    inquiry_info *info = ptr;
                    //得到device of class的值
                    uint32_t class = info->dev_class[0] |
                                                    (info->dev_class[1] << 8) |
                                                    (info->dev_class[2] << 16);
                    //这个是没有rssi的信息的,所以传入0,最后一个是ext的data,这里也是没有的,具体见7.5分析
                    btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
                                                                    0, NULL);
                    ptr += INQUIRY_INFO_SIZE;
            }
    }
    

    在这里我们先暂停一下,我们发现这里还有个rssi参数,以及data参数,在这个event中都是没有传入的,难道还有什么event是有这些参数的,你猜对了,所以这里我插播另外几个用来表示inquiry resultevent。它们分别是inquiry result with rssi event以及extended inquiryresulte event.


    7.3 inquiry result withrssi event的介绍

             这个eventinquiryresult event所表露的信息更多一点,他在spec中的定义如下:

    我们可以很清晰地看出来,inquiryresult有的东西他都有(少了一个reserved,其实我们不会关注啦),在最后他还多了一个参数就是rssi。这个参数意思是:

    Rssi:他是用来表示信号强度的,值越高越好。一般我们认为低于-90就是信号不好了。

    注:若是想controller能返回这个event,需要通过writeinquiry mode cmd中吧inquiry mode参数设为0x01.

    可以想象,他在android的代码中的实现和上面的差别就在于把那个rssinull换成对应的event返回值即可。大家可以自己去看。

    7.4 extended inquiryresult event介绍

             这个event和上面两个event大同小异,差别在于它有多了一点信息,就是extended inquiry response

    该参数的介绍如下:

    Extended Inquiry Response一共是由240byte组成,分为significant部分和non-significant部分。significant部分由一系列的EIRdata构成,每个EIR data由一个1byte的长度域和这个长度的data域组成。其中,n byte的长度用来表示EIR datatype,剩余的长度减去n就是真正的EIR dataNon significant部分就是用来补充significant部分剩余的byte的,他必须全部是0。其实就是我们检测到长度域为0的情况就应该不会再往下看了。

             一般而言,EIR data可以包括设备名字,TXpower levelserviceclass UUID,以及设备制造商的一些数据等等。我们希望host能够控制这个数据不要超过240byte

             看到这里,你不禁会问,这个nbyteEIR datatype究竟是怎么回事,这个n又是什么,一般而言,有以下 EIR Data type比较重要。

    1Service Class UUIDs

             这里会有三种UUID有可能返回,他们分别是16bit32bit以及128bituuids。需要注意的是EIRData type不仅看以表示究竟是16bit32bit还是126bit,还可以表示,这个UUID的列表是否是complete还是说仍有没有显示的UUID。他的type value见下表:


    所以,还是蛮清晰的吧,若是type value的值是05,则表示是一个32bitservice UUIDS,并且是一个complete listvalue

    2Local Name

             这个data是用来表示设备的名字的,有两种类型设备的名字,一种就是complete的,也就是通常意义上的设备名字,另外一种则是shorten,表示名字太长,这里没有全部显示出来。需要host再发送remote name request去获得这个名字。它的type value如下表:

    也就是value type0x08就是shortened的名字,还是很好理解的。

    3flags

             这个type主要用来表示一些LEBR/EDR的内容,具体如下:


    需要注意的是在BR/EDR的通道上,我们不能回应BR/EDRNOT Support。当然上面两个LE LimitedLE General Discoverable ModeBR/EDR中是不响应的。忽略即可。总的来说这个flags用得不是很多。

    4Manufacture Specific Data

             这个就是厂商的一些特殊的data,我们只需要知道他的value0xff即可。还有就是这个type的开始2byte需要些对应的厂商在sig中的编号。

    5TX Power Level

             他的格式如下表所示,有了这个和上文的RSSI,我们就可以用来判断path loose了。简单的一个应用就是我们通过手机的蓝牙来实现电脑的自动锁屏和解锁,比如说我离电脑较远,我就锁上屏幕,回来了之后就把屏幕解锁。

    当然,有必要说明的是,这个值其实并不是那么可靠,只能说我们只能用来参考罢了。

             大概比较常见的就是这几个EIRData Type了,大家知道后我们看代码就清晰多了。

    注:在host的实现中,并不需要对每一个EIRData type都解析,若是不能解析就跳过去,看下一个data的内容即可。

             这个eventandroid中的代码处理如下:

     //把扫描到的设备信息加入到found device中去
                    btd_event_device_found(&dev->bdaddr, &info->bdaddr, class,
                                                    info->rssi, info->data);
    

    和上面的差别就在于又多传入了一个eir data的指针进去了,也就是解析这个data了。

    7.5 btd_event_device_found的分析

             这个地方就是对上述的7.2~7.4中的各个event的统一处理函数了。他的代码分析如下:

    void btd_event_device_found(bdaddr_t *local, bdaddr_t *peer, uint32_t class,
                                    int8_t rssi, uint8_t *data)
    {
            struct btd_adapter *adapter;
    
            //local是本机的bdaddr, peer是搜索到的bdaddr, class是class of device的值
            //找到对应的adapter
            adapter = manager_find_adapter(local);
            if (!adapter) {
                    error("No matching adapter found");
                    return;
            }
    
            //把最新看到的设备加入到lastseen文件中
            update_lastseen(local, peer);
            //写入到classes文件中
            write_remote_class(local, peer, class);
    
            //若有EIR Data内容,写入到eir文件中
            if (data)
                    write_remote_eir(local, peer, data);
    
            //找到device后的一系列操作
            adapter_update_found_devices(adapter, peer, class, rssi, data);
    }
    
    void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
                                                    uint32_t class, int8_t rssi,
                                                    uint8_t *data)
    {
            struct remote_dev_info *dev, match;
            struct eir_data eir_data;
            char *alias, *name;
            gboolean legacy, le;
            name_status_t name_status;
            int err;
    
            memset(&eir_data, 0, sizeof(eir_data));
            //解析eir data,详细见7.5.1
            err = eir_parse(&eir_data, data);
            if (err < 0) {
                    error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
                    return;
            }
    
            //若是有name,并且同时是complete的,我们就写入到names
            if (eir_data.name != NULL && eir_data.name_complete)
                    write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);
    
            /* Device already seen in the discovery session ? */
            memset(&match, 0, sizeof(struct remote_dev_info));
            bacpy(&match.bdaddr, bdaddr);
            match.name_status = NAME_ANY;
            //看found device列表里面有没有这个设备
            dev = adapter_search_found_devices(adapter, &match);
            if (dev) {
                    //若是有,则把这个设备从oor device列表中remove
                    adapter->oor_devices = g_slist_remove(adapter->oor_devices,
                                                            dev);
                    //看rssi有没有变化,若有变化,到done,根据rssi重新排序
                    if (dev->rssi != rssi)
                            goto done;
    
                    //把eir data free掉
                    eir_data_free(&eir_data);
    
                    return;
            }
    
            /* New device in the discovery session */
    
            //得到保存的名字,eir data在上面已经更新过了
            name = read_stored_data(&adapter->bdaddr, bdaddr, "names");
    
            //flags就是le和bredr的一些内容判断
            if (eir_data.flags < 0) {
                    le = FALSE;
    
                    legacy = pairing_is_legacy(&adapter->bdaddr, bdaddr, data,
                                                                            name);
    
                    //没有name,并且支持name resolv,则置为NAME——required,就是待会会发remote name request出去
                   if (!name && main_opts.name_resolv &&
                                    adapter_has_discov_sessions(adapter))
                            name_status = NAME_REQUIRED;
                    else
                            //否则就不会requiry name
                            name_status = NAME_NOT_REQUIRED;
            } else {
                    le = TRUE;
                    legacy = FALSE;
                    name_status = NAME_NOT_REQUIRED;
            }
    
            //找到aliases,就是别名
            alias = read_stored_data(&adapter->bdaddr, bdaddr, "aliases");
            if (!eir_data.name_complete) {
                    //若是没有name complete,则也会发name request
                    name_status = NAME_REQUIRED;
            }
    
            //一个新的found的device
            dev = found_device_new(bdaddr, le, name, alias, class, legacy,
                                                    name_status, eir_data.flags);
            //释放name和alias空间
            free(name);
            free(alias);
    
            //加入到found devices列表中
            adapter->found_devices = g_slist_prepend(adapter->found_devices, dev);
    done:
            //重新赋值rssi
            dev->rssi = rssi;
            //根据rssi进行排序
            adapter->found_devices = g_slist_sort(adapter->found_devices,
                                                    (GCompareFunc) dev_rssi_cmp);
    
            //把同样的uuid去除掉
            g_slist_foreach(eir_data.services, remove_same_uuid, dev);
            g_slist_foreach(eir_data.services, dev_prepend_uuid, dev);
    
            //上报device found,见7.5.2
            adapter_emit_device_found(adapter, dev);
    
            //释放eir data的空间
            eir_data_free(&eir_data);
    }
    

    7.5.1 eir data的解析

             其实在上面我们了解了eirdata的组成之后,对于解析的方法也就水到渠成了。看一下下面的代码,我们就会发现其实不难。

    int eir_parse(struct eir_data *eir, uint8_t *eir_data)
    {
            uint16_t len = 0;
            size_t total;
            size_t uuid16_count = 0;
            size_t uuid32_count = 0;
            size_t uuid128_count = 0;
            uint8_t *uuid16 = NULL;
            uint8_t *uuid32 = NULL;
            uint8_t *uuid128 = NULL;
            uuid_t service;
            char *uuid_str;
            unsigned int i;
    
            eir->flags = -1;
    
            /* No EIR data to parse */
            if (eir_data == NULL)
                    return 0;
    
            while (len < HCI_MAX_EIR_LENGTH - 1) {
                    uint8_t field_len = eir_data[0];
    
                    /* Check for the end of EIR */
                    if (field_len == 0)
                            break;
    
                    switch (eir_data[1]) {
                    //看eir data的type来进行处理
                    case EIR_UUID16_SOME:
                    case EIR_UUID16_ALL:
                            uuid16_count = field_len / 2;
                            uuid16 = &eir_data[2];
                            break;
                    case EIR_UUID32_SOME:
                    case EIR_UUID32_ALL:
                            uuid32_count = field_len / 4;
                            uuid32 = &eir_data[2];
                            break;
                    case EIR_UUID128_SOME:
                    case EIR_UUID128_ALL:
                            uuid128_count = field_len / 16;
                            uuid128 = &eir_data[2];
                            break;
                    case EIR_FLAGS:
                            eir->flags = eir_data[2];
                            break;
                    case EIR_NAME_SHORT:
                    case EIR_NAME_COMPLETE:
                            //保存名字到eir name中,还有name——complete位来表示时short还是complete
                            if (g_utf8_validate((char *) &eir_data[2],
                                                            field_len - 1, NULL))
                                    eir->name = g_strndup((char *) &eir_data[2],
                                                                    field_len - 1);
                            else
                                    eir->name = g_strdup("");
                            eir->name_complete = eir_data[1] == EIR_NAME_COMPLETE;
                            break;
                    }
    
                    len += field_len + 1;
                    eir_data += field_len + 1;
            }
    
            /* Bail out if got incorrect length */
            if (len > HCI_MAX_EIR_LENGTH)
                    return -EINVAL;
    
            total = uuid16_count + uuid32_count + uuid128_count;
    
            //没有uuid的解析,我们就直接返回
            /* No UUIDs were parsed, so skip code below */
            if (!total)
                    return 0;
    
            /* Generate uuids in SDP format (EIR data is Little Endian) */
            //eir->services的构建,和sdp的格式类似
            service.type = SDP_UUID16;
            for (i = 0; i < uuid16_count; i++) {
                    uint16_t val16 = uuid16[1];
    
                    val16 = (val16 << 8) + uuid16[0];
                    service.value.uuid16 = val16;
                    uuid_str = bt_uuid2string(&service);
                    eir->services = g_slist_append(eir->services, uuid_str);
                    uuid16 += 2;
            }
    ……
    }
    

    7.5.2 device found的上报

             该函数的主要工作就是把刚刚反馈上来的设备信息回报到上层。


    void adapter_emit_device_found(struct btd_adapter *adapter,
                                                    struct remote_dev_info *dev)
    {
            struct btd_device *device;
            char peer_addr[18], local_addr[18];
            const char *icon, *paddr = peer_addr;
            dbus_bool_t paired = FALSE;
            dbus_int16_t rssi = dev->rssi;
            char *alias;
            size_t uuid_count;
    
            ba2str(&dev->bdaddr, peer_addr);
            ba2str(&adapter->bdaddr, local_addr);
    
            //找到对应的device
            device = adapter_find_device(adapter, paddr);
            //检查device是否已经配对
            if (device)
                    paired = device_is_paired(device);
    
            /* The uuids string array is updated only if necessary */
            //device services的uuid count
            uuid_count = g_slist_length(dev->services);
            //重新赋值一下dev的uuid count变量
            if (dev->services && dev->uuid_count != uuid_count) {
                    g_strfreev(dev->uuids);
                    dev->uuids = strlist2array(dev->services);
                    dev->uuid_count = uuid_count;
            }
            //若是le的设备,我们暂时不关注
            if (dev->le) {
                    gboolean broadcaster;
    
                    if (dev->flags & (EIR_LIM_DISC | EIR_GEN_DISC))
                            broadcaster = FALSE;
                    else
                            broadcaster = TRUE;
    
                    emit_device_found(adapter->path, paddr,
                                    "Address", DBUS_TYPE_STRING, &paddr,
                                    "RSSI", DBUS_TYPE_INT16, &rssi,
                                    "Name", DBUS_TYPE_STRING, &dev->name,
                                    "Paired", DBUS_TYPE_BOOLEAN, &paired,
                                    "Broadcaster", DBUS_TYPE_BOOLEAN, &broadcaster,
                                    "UUIDs", DBUS_TYPE_ARRAY, &dev->uuids, uuid_count,
                                    NULL);
                    return;
            }
    
            //根据对应的class来返回对应的字符信息,就是那个主设备
            icon = class_to_icon(dev->class);
    
            //若是没有别名,就把name拷贝过去,若是连名字都没有,就是地址了
            if (!dev->alias) {
                    if (!dev->name) {
                            alias = g_strdup(peer_addr);
                            g_strdelimit(alias, ":", '-');
                    } else
                            alias = g_strdup(dev->name);
            } else
                    alias = g_strdup(dev->alias);
    
            //通过Devicefound来向上层回报一系列的信息
            emit_device_found(adapter->path, paddr,
                            "Address", DBUS_TYPE_STRING, &paddr,
                            "Class", DBUS_TYPE_UINT32, &dev->class,
                            "Icon", DBUS_TYPE_STRING, &icon,
                            "RSSI", DBUS_TYPE_INT16, &rssi,
                            "Name", DBUS_TYPE_STRING, &dev->name,
                            "Alias", DBUS_TYPE_STRING, &alias,
                            "LegacyPairing", DBUS_TYPE_BOOLEAN, &dev->legacy,
                            "Paired", DBUS_TYPE_BOOLEAN, &paired,
                            "UUIDs", DBUS_TYPE_ARRAY, &dev->uuids, uuid_count,
                            NULL);
    
            g_free(alias);
    }
    
    至此,bluez这边搜索到一个设备的信息处理就全部结束了,它向上层回报了一个device foundsignal,下面我们随便想想都可以猜到,肯定就是上层显示搜索到的设备了。

    若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·
    
    展开全文
  • 目前在建设一个微信公众号项目,用vue,想实现一个聊天...大概的意思就是点击添加图片按钮就可以选择图片,然后选中图片之后直接在了解界面发送出去,类似微信或者QQ聊天效果,只需要可发送文字和图片即可, 万分感谢.
  • 这个图画有点丑,凑合看,意思大概就是这样。 接下来,我就得追踪下这个问题了,开始时我几乎就一口咬定是接口返回有问题,由于前几次后端没有日志,好像之前的反馈就那么过去了,直到后面又出现一次重复笔记...

    问题背景

    前不久我们项目中由用户反馈说遇到笔记重复的问题,而且不只一次遇到类似的反馈。

    这种重复笔记总是出现的feed流的中间位置,如下示意图所示:

    这个图画的有点丑,凑合看,意思大概就是这样的。

    接下来,我就得追踪下这个问题了,开始时我几乎就一口咬定是接口返回的有问题,由于前几次后端没有日志,好像之前的反馈就那么过去了,直到后面又出现一次重复笔记的问题,这次是公司内部员工出现的,于是后端也通过这个抓到了相应的日志,发现返回的笔记的确没有重复的,这下跑不掉了,就是前端的问题。

    问题排查

    于是,我又重新梳理了下代码流程,发现有一处比较有嫌疑:

            ...
            if (...) {
                mItems[0] = noteItem
            } else {
                mItems.add(0, noteItem)
            }
            mAdapter.items = mItems
            mAdapter.notifyItemChanged(0)
            ...
    

    鉴于是公司项目,我就省略掉业务逻辑了,这里的代码按照开发者的意图是当RecyclerView第一个item如果已经是noteItem这种类型的时候,我们就将这个位置item替换成最新的,如果这个位置的item不是noteItem这个数据的话,我们需要手动把它添加到第一个位置去,到这里实际上都没有什么问题。

    但是,当我看到mAdapter.notifyItemChanged(0)这个方法,直觉告诉我这里好像有点问题,当上面的逻辑走到else这里的时候,会往list里add一个新的item,但是这时候调用的刷新方法却是notifyItemChanged(0)。

    这个notifyItemChanged明显是刷新某个item的方法,即当这个item里的数据有变化时,调用这个方法去刷新这个item区域的UI,但是如果我们在adapter中add了一个新的item,再调用这个方法明显是不行的,这里是导致重复的原因嘛,我其实也不太确定。

    问题复现

    于是我写了一个Demo试了下。

    class RecyclerViewActivity : AppCompatActivity() {
    
        private val mDataList = ArrayList<Any>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_recycler_view)
    
            val layoutManager = LinearLayoutManager(this)
            layoutManager.orientation = RecyclerView.VERTICAL
            recyclerView.layoutManager = layoutManager
    
            val customAdapter =  CustomAdapter(mDataList)
    
            recyclerView.adapter = customAdapter
    
            for (i in 0..5) {
                mDataList.add("text: $i")
            }
    
            recyclerView.adapter?.notifyDataSetChanged()
        }
    
        //刷新方法
        fun refresh(view: View) {
            mDataList.add(0, "add item")
            recyclerView.adapter?.notifyItemChanged(0)
        }
    
    }
    

    构造一个普通的feed列表,每次点击刷新按钮,就会调用刷新方法,调用刷新方法的时候往index为0的位置再add一个item,然后再调用notifyItemChanged(0)方法,上下滑动后,发现数据是重复了。

    下面放个gif图展示下效果。

    从gif图中可以看到,点击刷新按钮,添加了”add item“,往下滑动后,出现了两个”text:5“的item,这个就是重复的item。

    问题原因

    我们看到notifyItemChanged的文档说明:

    notifyItemChanged(int position)
    This is an item change event, not a structural change event.

    RecyclerView中有两种不同数据改变事件,一种叫(item changes)项目改变,另一种叫(structual changes)结构改变。项目改变指的是某个单个item的数据发生变化,这个时候没有位置的改变。而structual changes则是有位置的变化发生,主要是数据源的变化会导致RecyclerView item位置发生变化。

    我们这个问题是我们往数据源前面加了一个item,这个时候应该需要调用具有structual changes 的方法来刷新,而不是采用notifyItemChanged来刷新,因为notifyItemChanged是一个item changes 的方法。

    展开全文
  • 昨天碰到一个小问题在一个ajax效果实现时候,火狐报错,内容意思大概是“函数字符串解析错误”,于是用alert(),发现var result = eval(xmlhttp.responseText); 这句eval函数报错,xmlhttp.responseText可以正常...

    昨天碰到一个小问题
    在一个ajax效果实现的时候,火狐报错,内容意思大概是“函数字符串解析错误”,于是用alert(),发现

    var result = eval(xmlhttp.responseText);

    这句eval函数报错,xmlhttp.responseText可以正常弹出,但只要是eval函数一解析,就会报错,并且不显示数据;蛋疼的我只好在一般处理程序中开始设置断点,查询错误,不知道原因的我一开始就将问题锁定在了反馈值这上面,但发现字符串的json格式没有问题~,内容也都OK,虽然看到了几个<br />,但是没有在意(话说回来,哪个公司的合格的编辑人员会在标题里打回车??我作为一个程序员都明白编辑人员的一些基本操作要求和常识,能在这么大的公司里遇到这种编辑组,我真tm是荣幸!)
    于是纠结的我,在百度上查询了eval相关的函数,发现原来eval函数在解析的时候,不能在字符串里含有"\r""\n""<br />"换行符,于是在一般处理程序返回的时候,我对字符串进行了替换字符处理

    result = result.Replace("\n", "").Replace("\r", "").Replace("<br />","");

    最后问题得到了解决~
    总结:问题不大,但是可以看到一些不爽的地方,先说自己的问题,作为一个程序,明知道输出的是title标题类型的数据,就应该对字符串进行相应的处理,这是其一;其二,了解的东西较少,导致解决问题效率降低。这是自身存在的两大问题,应该及时改变!希望各位大菜鸟给我这个小菜鸟提提建议。。。让我也能尽早的飞起来~

    转载于:https://www.cnblogs.com/Scorpion-Lan/archive/2011/08/11/2134900.html

    展开全文
  • 相信重复力量

    2019-01-25 00:27:55
    记得有句话说,“每天做一样事,却期待有不同结果,是十分愚蠢”,原句大概就是这个意思吧,不知道这句话出自哪里,我有没有断章取义,如果这句话真是这样的意思,那每天如果重复做一样但是正确是呢?...

    记得有句话说,“每天做一样的事,却期待有不同的结果,是十分愚蠢的”,原句大概就是这个意思吧,不知道这句话出自哪里,我有没有断章取义,如果这句话真的是这样的意思,那每天如果重复做一样的但是正确的是呢?长年累月中量的积累必然会带来质的提升吧?

    重复的积累带来质的变化应该是建立在“刻意练习”之上的,如果只是每天重复做一样的事,没有必要的反馈,或是没有根据反馈总结经验,在下一次重复的时候进行改进提升,那么期待不断地重复带来质变显然是不现实的。

    重复的力量同样在《异类》中得到了论证,《异类》中提到的一万小时理论,不就是建立在不断重复的基础上么?一个人想要成为一个领域的顶尖专家,需要的只是一万个小时刻意的重复练习。一万个小时的积累,不简单,但也不是不可能完成的。每天学习一个领域的知识,刻意练习,每天 3 小时,坚持十年,就完成了一万个小时的积累。这需要一个人不断地坚持,坚持下去,每天进步一点点,而不是间歇性疯狂地“努力”,努力应该成为生活的常态,虽然你每天没有达到疯狂地努力(当然,那样也挺好),但如果你每天都坚持改变,让自已成为比昨天更好的自己,10 年后的你一定会感谢从今天开始努力的自己。

    展开全文
  • 起因是学习群里有朋友提了一个问题,大概意思是这样子: 首先用时间函数对于表中ARRIVE_TIME进行相减操作,然后再获得需要与之对应数据 比如,我想查找表中ARRIVE_TIME距离今天2天数据 我第一反应...
  • 近期苹果审核有些诡异了,...说是二个问题: 1、宣传图里有年龄偏小的描述,“小表砸”,我们选择的评级是9+,但反馈的邮件大概意思是说要描述要支持3+; 2、从去年开始,我们一直使用IDFA,用来广告投放以及运营数...
  • 今天是2020年第一天,写了一行代码提交了,但是GitHub怎么没有给我统计到 ...大概意思就是,提交邮件和GitHub设置邮件不一致导致 解决办法:要更改现有提交中记录名称和/或电子邮件地址,您必须重写 Git ...
  • MVC中使用signalR入门教程

    万次阅读 2016-11-15 01:25:19
    好吧还是说说正经,厂里牛哥昨天分配给我一个任务,大概的一个意思就是“用这个signalR发送一条消息给客户端,客户端进行反馈响应”。任务听起来似乎很简单,但是没接触过signalR这玩意,我也是挺郁闷了...
  • 我也能给出具体答案,大概是需要不断去培养自己这方面的意思,只能告诉他们多看、多写,不断去推倒以前代码重构,看看《代码简洁之道》等等。今天要推荐项目 wtfjs,是一个收集有趣和诡异 JavaScrip 代码....
  •  讲通俗易懂一点,用一个曾经听过笑话来比喻,大概意思就是本飞机被我劫持了,其他劫持者等下次吧。这个电容就是本次劫机者。  晶振电路其实是个电容三点式振荡电路,输出是正玄波晶体等效于电感,加两...
  • 您即将提交信息不安全

    千次阅读 2020-12-15 16:03:50
    大概意思就是http访问不安全,需要升级为https访问才行。 注意:这个是谷歌浏览器提示,其他浏览器不存在这个问题。 二、解决 原配置如下: server { listen 80; server_name XXX.com; location / { ...
  • 在上周客户反馈了一个问题,大概意思是在他windows上安装识别软件中,识别一百多张内容比较复杂图片时,出现了“刚开始识别没问题,但是识别到100来张时发现之后图片都不识别了,没有识别结果”。...
  • (第一天)0到1思考做个什么样大学生公众号前言: 作为一只大三程序猿,颓废了两个月,迷茫了两个月 以前认识项目经理和师兄都说我是闲出来。经理建议我去做个公众号,作为自己...项目驱动学习,大概这个意思
  • 英语学习计划调整

    2015-06-09 11:30:38
    博客:...但是根据我学习反馈来看,目前看 扇贝新闻 上分类标签为高中文章相对比较容易,越往上就越难,’相对’的意思非常模糊,因为很多时候,我只能对文章做一个大概的理解,很多
  • 结果反馈的人全部用的是IE, :shock: ,唉,可恶的IE ,一个不按标准行事的家伙,可是还是有那么多fans。 问题来了当然要解决了,上网搜了又搜,终于发现是js加载顺序惹的祸。下面附上解决办法, [code="java...
  • 这些虽然我们脱口而出,但不实践很难领悟这些,意思是看到信号通过这些器件后,大概会是怎样,因为固定基本电路,模电上都有,看书就知道了,但实际应用电路,大部分都是书上基本电路,加一些电感,电容,三极管,...
  • 微服务本身并没有一个严格定义,不过从很多人的反馈来看,大家都达成了这样一个共识:微服务是一种简单应用,大概有10到100行代码。我知道使用代码行数来比较实现其实很不靠谱,因此你能理解这个意思就行,不必...
  • 异常分析 最近测试端反馈,商品详情里某些图片无法展现,后来...打眼一看就知道大概意思,这是加载https图片时 证书验证出错了,正常情况下我们平台商品都是上传到阿里云,没有出过这个异常信息,但是某些商品来源
  • 在这本书中,讲到了一个航海地图故事,大概意思是:一个要去航海船长,如果他想使用已知航海导航图,他必须把他在航海过程中获得新导航信息反馈回来,作为信息交换。这样话,越往后面使用航海导航图.....
  • 网页进度条能够更好...因此我们需要通过html代码逐行加载特性,在整页代码若干个跳跃行数中设置节点,进行大概的模糊进度反馈来实现进度加载效果。大致意思是:页面每加载到指定区域,则返回(n)%进度结果,
  •  高性能CPU和SSD带来极快加载速度,3D音效和触觉反馈带来身临其境游戏体验,很多向后兼容PS5游戏和PS4游戏会有更好画质(大概意思)。  包装内容:PS5主机及底座、无线手动开关、HDMI线缆、交流电
  • 没有任何敏感词汇,也不知怎么又被要求修改。也罢,再删。未删节版还请关注我...截止目前我收到实际反馈,享久2代有效率最高大概达到95-97%左右,即对于95%以上人有好延时效果同时不错体验。(更高端享...
  • Android应用ANR分析

    2019-06-13 17:46:11
    Application Not Responding,字面意思就是应用无响应,稍加解释就是用户一些操作无法从应用中获取反馈。在实际应用中应当去避免这种现象,虽然他暂时不会造成应用崩溃,但是却极大损坏了用户体验。 二.ANR...
  • 早上接到一个ABB机器人...二,将示教器和线缆单独换到热成型一线ABB机器人控制器上三,开机测试,示教器停留在此画面,提示:Connecting to the robot controller,大概意思是控制器与示教器通讯异常。四,由此检查...

空空如也

空空如也

1 2 3 4
收藏数 70
精华内容 28
关键字:

反馈的大概意思