程序猿

程序猿

Python 之父 Guido van Rossum 正式加入微软搞开源!

技术交流王叫兽 发表了文章 • 0 个评论 • 42 次浏览 • 2020-11-13 10:39 • 来自相关话题

今天,Python 之父 Guido van Rossum 在 Twitter 上正式宣布,退休太无聊,如今加入了微软开发者部门。Guido van Rossum 去年宣布退出 Python 核心决策层事实上,近几年来,随着人工智能的飞速发展,Python 横... ...查看全部

今天,Python 之父 Guido van Rossum 在 Twitter 上正式宣布,退休太无聊,如今加入了微软开发者部门。在这里插入图片描述

Guido van Rossum 去年宣布退出 Python 核心决策层

事实上,近几年来,随着人工智能的飞速发展,Python 横扫各大编程语言榜单,成为最受欢迎的程序设计语言之一。作为 Python 的创建者,Guido van Rossum 一边致力于 Python 社区维护,一边在 Dropbox 公司任职六年半后,突然于去年 10 月宣布将要退休,退出 Python 核心决策层。

在这里插入图片描述

彼时,Guido van Rossum 发布邮件表示,“我不想再为 PEP(Python 改进提案)[ PEP 572 ] 如此劳心劳力了,(而且尽管我在进行着如此艰难的战斗)却发现仍然有很多人不满意我所做出的决定。”

而后,被称为 “仁慈的终生独裁者”(BDFL,Benevolent Dictator for Life)的 Guido Van Rossum 在接受媒体采访时,回应退出的缘由:

所谓的终生和独裁都仅仅是玩笑。实际上,最近十年,退休的念头都在我脑海里徘徊。

我年龄已经不小了,身体也有一些问题。作为 Python 社区的主要负责人,我需要一遍又一遍地去教社区的其他成员如何开展工作,同时需要一遍又一遍地向 Python 新人解释 Python 的语言哲学,这样超负荷的工作让我的健康状况更为恶化。

事情的引爆点在于一个颇具争议的 Python 改进提案(PEP 572),当我接受这个提案之后,Twitter 等社交媒体上出现了一些中伤我的评论。而更为心寒的是,这些评论居然大多来自 Python 的核心成员,我对他们失望至极!

退休太无聊

如今看来,大佬的退休并不意味真正的离开。

Guido van Rossum 最新表示,退休太无聊,在微软,他将致力于“确保更好地使用 Python(不仅限于 Windows)。”

对此,一个微软发言人表示,该公司也没有其他细节可分享,但证实了 Guido van Rossum 确实已经加入了微软。“我们很高兴能将他加入开发者部门。微软致力于为 Python 社区做出贡献,并与之一起成长,而 Guido 的入职就是这一承诺的体现。”

同时,在该条 Twitter 下方,大神 Anders Hejlsberg(Delphi、C#、Typescript 发明人)表示期待与 Guido van Rossum 一起工作。

Python 之父 Guido van Rossum

上世纪 80 年代末,Guido 因对已有编程语言失望,决心开发一门易用且功能强大的新语言 Python。对此,他仅用了 3 个月的时间就开发了 Python 原型。

在 20 世纪 90 年代中期,他继续在美国国家标准技术研究院及之后的多家公司中积极从事该语言的工作,包括担任 Python Labs 的主管等。

在去 Dropbox 之前,他曾在 Google 工作,从 2005 年到 2012 年。在那里,他开发了内部代码审查工具 Mondrian,并应用于 Google App Engine。

如今,Guido van Rossum 选择加入微软,据悉,与 Typescript/C# 创始人 Anders,VS Code/Eclipse 创始人 Eric,Linux GNOME 作者Miguel 共同任职于微软全球资深副总裁潘正磊团队中,至于要做什么,其表示:

我认为退休很无聊,因此加入了 Microsoft 开发人员部门。做什么?选择太多了!但这肯定会使使用 Python 更好(而不仅仅是在Windows)。这里有很多开源。

同时,在微软深度拥抱开源的当下,Guido van Rossum 的加入,也如虎添翼。我们也将共同期待 Guido van Rossum 未来的发展。


融云 IM SDK 转 AndroidX

融云集成徐凤年 发表了文章 • 0 个评论 • 44 次浏览 • 2020-11-06 16:07 • 来自相关话题

最近公司项目要开发 IM 即时通信功能, 所以采用了融云即时通信 SDK。 但在集成的时候很快就发现了一个问题. 由于我们的工程是 AndroidX 的, 集成 Module 之后结果报错. 但是, 在融云官网却没有找到 Androidx 版本的 SDK.然后... ...查看全部

微信截图_20201106154036.png

最近公司项目要开发 IM 即时通信功能, 所以采用了融云即时通信 SDK。 但在集成的时候很快就发现了一个问题. 由于我们的工程是 AndroidX 的, 集成 Module 之后结果报错. 但是, 在融云官网却没有找到 Androidx 版本的 SDK.

然后自己通过查资料,然后在 gradle.properties 里的配置添加, 然后同步编译.

android.useAndroidX = trueandroid.enableJetifier = true

结果还是报错. 无奈之下找融云技术支持咨询一下. 技术支持同学告知, 如果工程原来就是 Androidx, 则需要先把 android.useAndroidX 和 android.enableJetifier 设置为 false, 同步编译一遍, 然后再设置成 true, 然后再同步编译, 这样就正确了。自己试了一下结果真的可以. 这可能是 Android Studio 的一个 bug 吧.

最后工程中代码中会提示不兼容类型的错误,但不影响编译运行。

技术支持同学也告知另一种更简单的方法, 就是直接使用容云官网提供的 maven 远程依赖方式使用 SDK 不会出现不兼容的问题, 亲测是可以的. 如果有遇到同样问题的童鞋可直接使用 maven 远程依赖库进行集成.


带你实现女朋友欲罢不能的 App

技术交流徐凤年 发表了文章 • 0 个评论 • 39 次浏览 • 2020-11-06 16:07 • 来自相关话题

前言带你实现女朋友欲罢不能的 App需求需要日记本,甜言蜜语要记录需要只能和 ta 聊天模块需要可以记录关键日期,避免忘记送命0202年了,Android开发大都应该是老油条了把。这太简单,我们开始动手。我知道没图是骗不到人的。先放图,大家看一下最终实现的效果... ...查看全部

前言

带你实现女朋友欲罢不能的 App

需求

  1. 需要日记本,甜言蜜语要记录

  2. 需要只能和 ta 聊天模块

  3. 需要可以记录关键日期,避免忘记送命
    0202年了,Android开发大都应该是老油条了把。这太简单,我们开始动手。
    我知道没图是骗不到人的。先放图,大家看一下最终实现的效果。
    banner.jpg

    即时通讯部分

    使用了融云 sdk 集成了单聊部分
    配置布局文件
    这是您的会话列表 Activity 对应的布局文件:conversationlist.xml。注意 android:name 固定为融云的 ConversationListFragment。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <fragment        android:id="@+id/conversationlist"        android:name="io.rong.imkit.fragment.ConversationListFragment"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

新建 Activity

public class ConversationListActivity extends FragmentActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.conversationlist);        FragmentManager fragmentManage = getSupportFragmentManager();        ConversationListFragment fragement = (ConversationListFragment) fragmentManage.findFragmentById(R.id.conversationlist);        Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()            .appendPath("conversationlist")            .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")             .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.APP_PUBLIC_SERVICE.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "true")            .build();        fragement.setUri(uri);    }  }
<!--会话列表--><activity    android:name="io.rong.fast.activity.ConversationListActivity"    android:screenOrientation="portrait"    android:windowSoftInputMode="stateHidden|adjustResize">    <intent-filter>        <action android:name="android.intent.action.VIEW" />        <category android:name="android.intent.category.DEFAULT" />        <data            android:host="io.rong.fast"            android:pathPrefix="/conversationlist"            android:scheme="rong" />    </intent-filter></activity>

其他部分参考
融云官网:https://www.rongcloud.cn/
文档频道:https://docs.rongcloud.cn/v4

纪念日部分

日历控件:https://juejin.im/post/6844903512007000077
其他部分如若有人需要,会尽快传到 github 。
github:https://github.com/yanxiame/rongcloud/tree/loverschat


关于融云聊天室KV 值的正确使用

融云集成徐凤年 发表了文章 • 0 个评论 • 44 次浏览 • 2020-11-06 16:07 • 来自相关话题

在使用融云集成即时通讯的过程中,根据产品业务逻辑,我们使用了融云聊天室场景,因为我们主要做的是直播聊天室的业务;在使用聊天室的过程中,了解到融云这边是有针对聊天室属性做处理的,这样的话,更加方便产品的某些功能点的实现,比如说 人数的动态变化等等;现就我这边了解... ...查看全部

微信截图_20201106154411.png

在使用融云集成即时通讯的过程中,根据产品业务逻辑,我们使用了融云聊天室场景,因为我们主要做的是直播聊天室的业务;在使用聊天室的过程中,了解到融云这边是有针对聊天室属性做处理的,这样的话,更加方便产品的某些功能点的实现,比如说 人数的动态变化等等;

现就我这边了解到的聊天室的KV 对大家做一个说明,增进对KV 使用的了解; 首先,要获取聊天室的属性,我们当然应该加入聊天室,加入聊天室的方式如下所示:

 RongIM.getInstance().joinChatRoom(roomId, 20, new RongIMClient.OperationCallback() {
        @Override
        public void onSuccess() {
        }
        @Override
        public void onError(RongIMClient.ErrorCode errorCode) {
        }
    });

以上方法无需多言,调用即可加入聊天室,具体参数文档可以参考融云文档

当然,要获取聊天室属性获取之前,肯定要知道如何设置聊天室属性的,以下方式主要展示客户端的设置方式:

 RongIMClient.getInstance().setChatRoomEntry(chatRoomId, key, value, sendNotification, isAutoDel, notificationExtra, new RongIMClient.OperationCallback() {
/**
 * 成功回调
 */
@Override
public void onSuccess() {
}
/**
 * 失败回调
 * @param errorCode 错误码
 */
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
}

接下来就是获取的方式了,这块是我在集成过程中花费时间比较久的,在获取之前,需要先了解融云对于聊天室KV 的整体流程设置:

  • 加入聊天室之后,通过设置的监听  setKVStatusListener 来获取到服务KV 的变化,然后在收到变化之后,在调用 getChatRoomEntry 来获取KV 值即可  。

    注意:前提条件是设置监听获取到KV 变化之后,才去获取,因为这个变化是服务发出的,也就是说这是一个通知状态;

    监听的设置方式:

 RongIMClient.getInstance().setKVStatusListener(new RongIMClient.KVStatusListener() {
     @Override
     public void onChatRoomKVSync(String roomId) {
     }
     @Override
     public void onChatRoomKVUpdate(String roomId, Map<String, String> chatRoomKvMap) {
     }
     @Override
     public void onChatRoomKVRemove(String roomId, Map<String, String> chatRoomKvMap) {
     }
 });

当服务的KV 发送变化时候,会在 onChatRoomKVUpdate 中回调到的,回调中的Map 就是变化得KV 值,当然可以用户主动调用来进行获取,方式如下:

  RongIMClient.getInstance().getAllChatRoomEntries(roomId, new RongIMClient.ResultCallback<Map<String, String>>() {
        @Override
        public void onSuccess(Map<String, String> stringStringMap) {
        }
        @Override
        public void onError(RongIMClient.ErrorCode e) {
        }
    });

通过以上步骤即可完成聊天室属性的设置,以及获取;

自定义消息 包含 list 数组

技术交流徐凤年 发表了文章 • 0 个评论 • 34 次浏览 • 2020-11-06 16:07 • 来自相关话题

公司产品越来越复杂,业务线也不断的增加,项目中聊天模块使用了融云的 sdk ,但是 sdk 中自带的消息类型有限,不能满足产品需要的多张图片布局的消息类型,只能自定义一个,但是发现没有包含 list 的消息例子,实现起来有点繁琐,这边给大家参考下。————消息... ...查看全部

微信截图_20201106154952.png

公司产品越来越复杂,业务线也不断的增加,项目中聊天模块使用了融云的 sdk ,但是 sdk 中自带的消息类型有限,不能满足产品需要的多张图片布局的消息类型,只能自定义一个,但是发现没有包含 list 的消息例子,实现起来有点繁琐,这边给大家参考下。
————消息体—————

  1. 新建一自定义消息类,继承 MessageContent

2.实现 encode() 方法,该方法的功能是将消息属性封装成 json 串,再将 json 串转成 byte 数组,该方法会在发消息时调用
注意:要在这个方法里面加上这句话用来携带用户信息
if (getJSONUserInfo() != null){
               jsonObj.putOpt(“user”, getJSONUserInfo());
           }

3.覆盖父类的 MessageContent(byte[] data) 构造方法,该方法将对收到的消息进行解析,先由 byte 转成 json 字符串,再将 json 中内容取出赋值给消息属性。
注意:要在这个方法里面加上这句话用来解析携带用户信息
 if (jsonObj.has(“user”))
               setUserInfo(parseJsonToUserInfo(jsonObj.getJSONObject(“user”)));

4.MessageContent 已实现 Parcelable 接口,自定义消息类也需要实现 Parcelable

5.增加注解信息 :注解名:MessageTag ;属性:value ,flag; value 即 ObjectName 是消息的唯一标识不可以重复,
开发者命名时不能以 RC 开头,避免和融云内置消息冲突;flag 是用来定义消息的可操作状态。
flag 值如下表:
枚举值 说明
MessageTag.NONE 为空值,不表示任何意义,发送的自定义消息不会在会话页面和会话列表中展示。
MessageTag.ISCOUNTED 表示客户端收到消息后,要进行未读消息计数(未读消息数增加 1),所有内容型消息都应该设置此值。非内容类消息暂不支持消息计数。
MessageTag.ISPERSISTED 表示客户端收到消息后,要进行存储,并在之后可以通过接口查询,存储后会在会话界面中显示。
MessageTag.STATUS 在本地不存储,不计入未读数,并且如果对方不在线,服务器会直接丢弃该消息,对方如果之后再上线也不会再收到此消息(聊天室类型除外,此类消息聊天室会视为普通消息)。

6.自定义消息应在 init 后注册 RongIM.registerMessageType(CustomizeMessage.class);
—————-自定义消息展示————-

package cn.rongcloud.demo;

import android.os.Parcel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import io.rong.common.ParcelUtils;
import io.rong.common.RLog;
import io.rong.imlib.MessageTag;
import io.rong.imlib.model.MessageContent;

@MessageTag(value = "sendGoodsLocal", flag = MessageTag.ISPERSISTED)
public class SendGoodsLocalMessage extends MessageContent {
    private String content;
    private String id;
    private int typeid;
    private List<String> img =new ArrayList<>();
    private SendGoodsLocalMessage() {
    }

    public SendGoodsLocalMessage(Parcel in) {
        this.content = ParcelUtils.readFromParcel(in);
        this.id = ParcelUtils.readFromParcel(in);
        this.typeid = ParcelUtils.readIntFromParcel(in);
        this.img = ParcelUtils.readListFromParcel(in,String.class);
    }

    public SendGoodsLocalMessage(byte[] data) {
        String jsonStr = null;
        try {
            jsonStr = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException var5) {
            RLog.e("GroupNotificationMessage", "UnsupportedEncodingException ", var5);
        }

        try {
            JSONObject jsonObj = new JSONObject(jsonStr);
            this.setContent(jsonObj.optString("content"));
            this.setId(jsonObj.optString("id"));
            this.setTypeid(jsonObj.optInt("typeid"));
            JSONArray jsonArray = jsonObj.optJSONArray("img");
            List<String> imgList = new ArrayList<>();
            for (int i = 0; i < jsonArray.length(); i++) {
                imgList.add((String) jsonArray.get(i));
            }
            setImg(imgList);
//            this.setImg();
        } catch (JSONException var4) {
            RLog.e("GroupNotificationMessage", "JSONException " + var4.getMessage());
        }

    }

    public static final Creator<SendGoodsLocalMessage> CREATOR = new Creator<SendGoodsLocalMessage>() {
        public SendGoodsLocalMessage createFromParcel(Parcel source) {
            return new SendGoodsLocalMessage(source);
        }

        public SendGoodsLocalMessage[] newArray(int size) {
            return new SendGoodsLocalMessage[size];
        }
    };

    public static SendGoodsLocalMessage obtain(String content, String id, int typeid, List<String> img) {
        SendGoodsLocalMessage obj = new SendGoodsLocalMessage();
        obj.content = content;
        obj.id = id;
        obj.typeid = typeid;
        obj.img = img;
        return obj;
    }

    public String getContent() {
        return content;
    }

    public List<String> getImg() {
        return img;
    }

    public void setImg(List<String> img) {
        this.img = img;
    }

    public int getTypeid() {
        return typeid;
    }

    public String getId() {
        return id;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setTypeid(int typeid) {
        this.typeid = typeid;
    }

    @Override
    public byte[] encode() {
        JSONObject jsonObj = new JSONObject();
        try {
            jsonObj.put("content", this.content);
            jsonObj.put("id", this.id);
            jsonObj.put("typeid", this.typeid);

            JSONArray jsonArray = new JSONArray();
            for (String name : img) {
                jsonArray.put(name);
            }
            jsonObj.put("img", jsonArray);

        } catch (JSONException var4) {
            RLog.e("GroupNotificationMessage", "JSONException " + var4.getMessage());
        }
        try {
            return jsonObj.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException var3) {
            RLog.e("GroupNotificationMessage", "UnsupportedEncodingException ", var3);
            return null;
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        ParcelUtils.writeToParcel(dest, this.content);
        ParcelUtils.writeToParcel(dest, this.id);
        ParcelUtils.writeToParcel(dest, this.typeid);
        ParcelUtils.writeToParcel(dest, this.img);
    }
}
package cn.rongcloud.demo;


import android.content.Context;
import android.content.Intent;
import android.text.Spannable;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import com.bumptech.glide.Glide;

import io.rong.imkit.model.ProviderTag;
import io.rong.imkit.model.UIMessage;
import io.rong.imkit.widget.provider.IContainerItemProvider;

@ProviderTag(
        messageContent = SendGoodsLocalMessage.class,
        showPortrait = false,
        centerInHorizontal = true,
        showProgress = false,
        showSummaryWithName = false
)
public class SendGoodsLocalProvider extends IContainerItemProvider.MessageProvider<SendGoodsLocalMessage> {

    @Override
    public void bindView(View v, int i, SendGoodsLocalMessage mSendGoodsLocalMessage, UIMessage uiMessage) {
        ViewHolder holder = (ViewHolder) v.getTag();
        holder.tvGoodsName.setText(mSendGoodsLocalMessage.getContent());
        Glide.with(v.getContext()).load(mSendGoodsLocalMessage.getImg().get(0)).centerCrop().into(holder.ivCover);
    }

    @Override
    public Spannable getContentSummary(Context context, SendGoodsLocalMessage message) {
        if (message == null) {
            return null;
        }
        return new SpannableString(message.getContent());
    }


    @Override
    public String getPushContent(Context context, UIMessage message) {
        return super.getPushContent(context, message);
    }

    @Override
    public Spannable getContentSummary(SendGoodsLocalMessage mSendGoodsLocalMessage) {
        return null;
    }

    @Override
    public void onItemClick(View view, int i, SendGoodsLocalMessage mSendGoodsLocalMessage, UIMessage uiMessage) {

    }

    @Override
    public View newView(Context context, ViewGroup viewGroup) {
        View view = LayoutInflater.from(context).inflate(R.layout.rc_send_goods_message, null);
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.tvGoodsName = view.findViewById(R.id.tvGoodsName);
        viewHolder.tvSend = view.findViewById(R.id.tvSend);
        viewHolder.ivCover = view.findViewById(R.id.ivCover);
        view.setTag(viewHolder);
        return view;
    }
    private static class ViewHolder {
        TextView tvGoodsName,tvSend;
        ImageView ivCover;
        private ViewHolder() {
        }
    }
}

大家可以当一个参考。


Flutter 集成融云 sdk

技术交流徐凤年 发表了文章 • 0 个评论 • 43 次浏览 • 2020-11-06 16:07 • 来自相关话题

前言1.集成 flutter 融云 sdk ,需要一个稳定的 flutter 环境,能正常的创建和运行项目。2.前期准备融云官网申请开发者账号通过管理后台的 “基本信息”->”App Key” 获取 AppKey3.通过管理后台的 “IM 服务”—>... ...查看全部

前言

1.集成 flutter 融云 sdk ,需要一个稳定的 flutter 环境,能正常的创建和运行项目。
2.前期准备融云官网申请开发者账号
通过管理后台的 “基本信息”->”App Key” 获取 AppKey
3.通过管理后台的 “IM 服务”—>”API 调用”->”用户服务”->”获取 Token”,通过用户 id 获取 IMToken
4.我知道没图是骗不到人的。先放图,大家看一下最终实现的效果。
BsvRVU.jpg

集成 sdk

依赖 IM Flutter plugin在项目的 pubspec.yaml 中写如下依赖。

dependencies:
  flutter:
    sdk: flutter
rongcloud_im_plugin: ^4.0.3
  1. 然后在项目路径执行 flutter packages get 来下载 Flutter Plugin。

  2. 我们写 2 个 button 和 2 个 text ,分别用来实现 init 和 connect 的事件和状态。

  3. 初始化 SDK

RongIMClient.init(RongAppKey);

4.连接 IM

RongIMClient.connect(RongIMToken, (int code, String userId) {
print('connect result ' + code.toString());
EventBus.instance.commit(EventKeys.UpdateNotificationQuietStatus, {});
if (code == 31004 || code == 12) {
Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute(builder: (context) => new LoginPage()), (route) => route == null);
} else if (code == 0) {
print("connect userId" + userId);
// 连接成功后打开数据库
// _initUserInfoCache();
}

全部代码参考

import 'package:flutter/material.dart';
import 'package:rongcloud_im_plugin/rongcloud_im_plugin.dart' as prefix;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _isInit ;
  var _isConnect ;
  void _init() {
    setState(() {
      prefix.RongIMClient.init("pvxdm17jpof6r");
      _isInit="已经初始化";
    });
  }
  void _connect() {
    setState(() {
      prefix.RongIMClient.connect("rbdI/5jrPxR4aQ2078HhWnHte7+VrAhsnSjOcYQ3SKOCXhodQlcZYZ5acv4syCtN0dsYRNvxZh44fo4VR5s+6A==", (code, userId){
        if(code == 0 ){
          _isConnect="连接成功";
        }else{
          _isConnect="连接失败";
        }
      });
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '$_isInit',
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              '$_isConnect',
              style: Theme.of(context).textTheme.headline4,
            ),
            MaterialButton(
              minWidth: 250.0,
              onPressed: () {_init();},
              colorBrightness: Brightness.dark,
              color: Colors.deepPurpleAccent,
              elevation: 20.0,
              splashColor: Colors.green,
              //highlightColor: Colors.red,
              highlightElevation: 1.0,
              child: Text("初始化"),
            ),
            MaterialButton(
              minWidth: 250.0,
              onPressed: () {_connect();},
              colorBrightness: Brightness.dark,
              color: Colors.deepPurpleAccent,
              elevation: 20.0,
              splashColor: Colors.green,
              //highlightColor: Colors.red,
              highlightElevation: 1.0,
              child: Text("连接"),
            ),
          ],
        ),
      ),
    );
  }
}


如果再给我一次机会,我希望我从未学过编程

技术交流徐凤年 发表了文章 • 0 个评论 • 31 次浏览 • 2020-11-04 14:39 • 来自相关话题

我是一名程序员。你可能会觉得我是专业的软件工程师,但实际上,软件工程不只是一个专业,还是一种生活方式。连帽衫、乒乓球、吃不完的零食和苏打水……都是这种生活的一部分。但虽然这个职业可以给人带来那么多回报,我还是要坦白一件事:有时我希望自己从来没有学过编程。怪癖自... ...查看全部

我是一名程序员。你可能会觉得我是专业的软件工程师,但实际上,软件工程不只是一个专业,还是一种生活方式。连帽衫、乒乓球、吃不完的零食和苏打水……都是这种生活的一部分。但虽然这个职业可以给人带来那么多回报,我还是要坦白一件事:

有时我希望自己从来没有学过编程。

怪癖

自从我开始学习编程以来,就再也不能像以前那样轻松地浏览网页了。我无法再平静地接受在各种网站上遇到的各种 bug。每当有奇怪的事情发生时,我的好奇心就上了头,然后就会打开浏览器开发工具开始调试网页。

尝试提交表单时出现加密错误消息?看到这样的错误,我会深入 JavaScript 控制台,查找错误消息,深入研究源代码,并仔细观察进进出出的网络请求。页面 UI 看起来有些过时,或者页面布局很漂亮?不管怎样,我都会调整浏览器窗口大小,检查页面响应屏幕尺寸的能力。什么?你竟然选择了 Comic Sans 字体?我可能永远不会再使用你或你们公司的产品了。

微信图片_20201104143349.jpg

请不要使用 ComicSans

职业生涯

觉得我的这些浏览习惯很怪异吗?这还不算啥,我和其他软件工程师的对话会让你印象更深刻的。总体而言,工程师往往固执己见。我们的血液中流淌着迂腐的基因。你喜欢使用空格还是 tabs 缩进代码?你更喜欢 Vim 还是 Emacs?Chrome 还是 Firefox?

聪明点的人会问到,这些对话“真的重要吗?”。Bikeshedding(在琐碎细节上浪费时间)是确实存在的现象,大家都需要经常反省。

微信图片_20201104143403.jpg

xkcd——真正的程序员

随着越来越多的公司采用敏捷方法,我们还得时常考虑在 Waterfall、Scrum 或 Kanban 开发生命周期之间权衡取舍。我们所有人都喜欢鄙视 Waterfall,毕竟这是老式的低效率公司所使用的遗留品。但是 Scrum 与看板之战还在继续。

你竟然是 Scrum 的信徒?我敢打赌,你为了满足那些 time box 会仓促提交混乱的代码,才能在冲刺结束之前赶上假想的时限。

微信图片_20201104143416.jpg

说到敏捷,故事的重点在哪里?时间尺度?努力?复杂性?风险?这些都有?你我可能会花费几小时时间来争论每个定义的优缺点,最后还是无法达成共识。

在某些时候,这种争论可能会演变为更多的 bikeshedding,但能够相互理解和有效沟通是至关重要的,其中就包括了对我们日常使用的术语达成共识。

前端开发带来的争论又是数不清的,其中最典型的是:“我们要到什么时候才会放弃对 Internet Explorer 的支持?”我必须在“讨厌 Internet Explorer,想要放弃它”和了解还在用它的客户需求之间找到完美的平衡点。

微信图片_20201104143428.jpg

持续学习

持续学习是每一位开发者必备的能力,因为技术形势日新月异。每月都有成百上千的新库和框架发布。JavaScript 倦怠不是什么幻觉,“学不动了”也不仅仅是调侃。

我得花一天的时间配置 Webpack、Rollup 和 Babel 以使用最新的 ES6+ 语法,而旁人听我这么说就像在听天书。Angular 和 AngularJS 截然不同?LitElement、Svelte 和 Stencil 似乎是很有前途的 Web 组件解决方案?Deno 可能是下一个 Node?听着都像是谜语。

当有人问我做什么工作时,我总会蹦出来一堆术语:“我通常使用前端技术,例如 HTML、CSS 和 JS。有时我必须使用 PHP 或 SQL,但我更多是 MEAN/MERN 栈开发人员。有时我使用 Heroku 之类的 PaaS 技术,还有时我会使用 AWS 或 GCP 之类的 IaaS 提供商。”

微信图片_20201104143437.jpg

个人生活

在业余时间里,我读的书干货十足,例如《干净代码》《重构》和《领域驱动设计》。我不是在看教科书,就是在阅读里面写着可疑建议的文章,或观看一些编程教程。关于编程的播客更能吸引人,这样我就能在路上听某人谈论写代码的方法,然后我又可以花一天时间谈相关话题了。

除了在线获取内容外,软件工程师还会花费大量个人时间来在网上创建内容。我个人的兴趣是构建简单的应用和游戏,其实没人看得到。这是浪费时间吗?也许是吧,但的确挺有意思的。


微信图片_20201104143447.jpg企业 BS 生成器应用

事实是

可事实是,编程给了我创造和创新的机会。它帮助我将创意变为现实,让我几乎从零开始构筑了很多东西。软件工程使我能够解决有趣而艰巨的挑战,理想情况下还能让人们的生活更轻松一些。编程使我的思维更具逻辑性。编程让我有机会不断学习,我还能以编程为职业获取薪水!

事实是,我喜欢编程。

参考阅读

https://hackernoon.com/i-wish-i-never-learned-to-code-7a1m3wwx

未来 10 年,软件开发涨工资的 8 个 技术发展趋势

技术交流王叫兽 发表了文章 • 1 个评论 • 59 次浏览 • 2020-10-20 16:13 • 来自相关话题

英文 | https://medium.com/better-programming/software-developer-trends-of-2020-and-beyond-d1b955bc46b8     &nb... ...查看全部
英文 | https://medium.com/better-programming/software-developer-trends-of-2020-and-beyond-d1b955bc46b8
 
 


 
新的一个十年来到,随之而来的是对技术变革和趋势的兴奋之潮。软件开发已成为世界几乎每个部门不可或缺的一部分,因此软件开发的发展和变化对我们的生活产生了巨大影响。尽管我们无法始终准确地预测技术的发展前景,但我们仍有望在新的十年中延续一些趋势。
 

 
以下是我们预测并讨论的在未来10年里软件开发技术的8个开发趋势。
 


 



1、人工智能将继续占主导地位


尽管人工智能已经存在了很多年,但它每年都在不断增长和增强,成为全球许多技术的基础。开发人员预测,随着越来越多的行业在基础架构中采用AI,人工智能将继续占主导地位。
 
2020年的最大趋势表明,医疗保健,教育,旅游行业和社交媒体将使用AI来提供个性化的体验,帮助和预测服务。人工智能将成为整个行业新的竞争优势,改变我们对人类参与和资源的思考方式。深度学习框架Tensorflow 2.0预计将主导市场。
 


 

2、Python预计会随着AI和Ml的发展而崛起


 


 
从ML研究到视频游戏开发再到Web开发,Python一直被证明是一种流行且广受欢迎的语言。由于ML和AI的发展正在上升,因此预计Python将在这种稳定的增长和普及中继续发展,特别是对于令人印象深刻的创新,包括ML驱动的聊天机器人。
 
尽管“增长最快”语言的概念可能很难确定,但数据表明Python可能是块不错的蛋糕。Python不仅用于各种流行领域和工作,而且入门门槛低,并且由新一代开发人员培育而成的支持社区。
 

 


 

3、5G可能是为开发人员打开大门的下一个重要物种


 
5G将于2020年进入市场。这个令人兴奋,更快的网络带来了开发人员需要解决的新问题。尽管存在诸多弊端和争议,但5G仍有可能革新手持设备,并为开发人员进入分布式技术的底层打开大门。
 
它为开发人员提供了开发更强大的应用程序和增强现实功能的机会。总体而言,预计5G将改变整个世界-从为智慧城市提供动力,到改善交通系统,再到增加网络扩展能力。
 
当然,5G的处理能力还带来了开发人员必须解决的问题,例如
  最近对天气预报技术的关注
 
  对覆盖范围不佳的吐槽
  。不管面临的挑战如何,该技术都是有前途的,值得学习投资。
 

 

 


 

4、边缘和云计算的使用预计会上升

与5G一同出现的还有
  边缘计算
  的潜力:一种分散式计算基础架构。边缘计算的高度分布式模型可能有助于克服云计算的缺点。这些发展可能是计算和工业的未来。
 
事实证明,云计算对于公司基础架构至关重要,并且随着网络安全问题的持续存在,各行各业的大公司都将云作为解决方案。
 
最重要的是,到2020年底,
  全球公共云服务收入
  预计将从2278亿美元增长到2664亿美元。边缘计算预计将随着云计算功能的升级而增长。实际上,预计
  全球Edge计算市场
  将从2018年的14.7亿美元增长到2025年的268.4亿美元。
 


 


 

5、预计会有新突破的语言:Rust,TypeScript,Kotlin和Swift


 
在过去的十年中,已经创建了数百种编程语言。这种从过去的单一语言的转变使开发人员能够使用专门的语言来工作,这些语言更加侧重于开发人员的人机工程学和硬件的现代化开发。
 
种类繁多的编程语言可使开发人员
  增强能力
 
  增强行业实力
  ,并将我们的重点转向解决人类问题。
  StackOverflow研究
  表明,到2020年,排名前四的现代编程语言将为Rust,TypeScript,Kotilin和Swift,其中Rust在过去四年中连续第四位。
 


 


 

6、 Kubernetes成为Mesos和Docker Swarm的胜利者


 
随着云计算的兴起,容器化应用程序的兴起。在这里,Kubernetes显然是赢家。随着云技术继续与我们的世界融合,Kubernetes将成为各地开发人员的重要工具。研究表明,Kubernetes的受欢迎程度持续上升。
  开发人员预测
  ,到2020年,我们将看到此流行应用程序的最佳实践和标准化的兴起。
 

 

 

 


 

7、Web框架:React继续发光


 
React对Web开发产生了巨大的影响,它带来的创新对开发人员都非常有用。它已被证明是过去一年中最主要的JavaScript框架。而统计数据表明,这种情况将持续数年。尽管其他框架(例如Vue)提供了自己独特的功能,但是
  React
  由于其灵活性和健壮性而受到许多人的
  青睐
 
 
而且,由于React得到了Facebook的支持,因此它将作为Web开发的标准在业界不断上升。查看这些Google趋势,以了解自2017年以来React在全球范围内的关注程度。
 

 



 

8、降低软件开发入门的门槛:会有越来越多的自学成才的程序员

尽管对技术行业有普遍的认识,但是软件开发的供需之间还是存在差距。随着全球大学价格的上涨,越来越少的人选择计算机科学专业。预计在未来几年内,软件开发人员的进入门槛将降低,从而为自学成才的开发人员腾出空间。
 
此外,一些开发人员预测,LCCS开发(低代码,无代码开发)将为企业创新提供增长,而无需CS学位持有者。
 
在线学习平台是行业转移的原因之一。Educative为所有级别的开发人员提供大学水平的课程,以提高他们的编码技能,并以低廉,无压力的成本处理新语言。2020年的目标是使世界各地的人们能够在没有大学负担的情况下加入发展世界,学习编程的队伍中来。
 


2020年Java语言发展现状

技术交流王叫兽 发表了文章 • 0 个评论 • 113 次浏览 • 2020-10-13 10:31 • 来自相关话题

作者 | Valeriia Karpenko译者 | 刘雅梦策划 | 陈思今年,Java 到达了一个不可思议的里程碑,达到了 25 岁的高龄。我们通过举办一个特别的在线 Java 日活动来庆祝它的诞生,在该活动中,许多专家演讲者分... ...查看全部
作者 | Valeriia Karpenko


译者 | 刘雅梦
策划 | 陈思

今年,Java 到达了一个不可思议的里程碑,达到了 25 岁的高龄。我们通过举办一个特别的在线 Java 日活动来庆祝它的诞生,在该活动中,许多专家演讲者分享了他们的经验,并就如何从这门语言中获得更多收益提供了技巧和窍门。

这引起了我们的思考,我们决定对数据进行深入研究,以彻底发现 Java 的普遍状态是什么,并帮助你回答一些亟待解决的问题。我们发现的某些内容可能是不足为奇的,但也有些见解是令人非常意想不到的。

随着 Java 15 在本周的发布,我们决定把它放在一起,向你展示 Java 的状态。这篇文章是根据不同来源的数据而创建的,其中包括我们的开发人员倡导者 Trisha Gee 的专家评论。

Java 开发者有多少,他们分布在哪里?

第一个问题是:“大多数的 Java 开发人员都在哪里,我们中有多少人是 Java 开发人员呢?”我们通过综合所能获取到的最准确的信息来回答这个问题,然后进行推断,得出一个我们认为非常合理的猜测。

市场研究和分析团队根据开发人员估算模型得出的最佳估计显示,当今世界上有大约 520 万专业 Java 开发人员,他们将 Java 作为主要语言。但是,如果我们将主要使用其他编程语言但同时也做一些 Java 工作的专业开发人员也包含在内的话,这个数字可能 接近 680 万。

至于这些 Java 开发人员都集中在什么地方,在亚洲居住的 Java 开发人员数量最多,那里大约有 250 万开发人员使用 Java 作为主要语言。北美和欧洲的数字远不及亚洲。你可能会问:“为什么呢?”好吧,起初我们有也有同样的想法,因此我们对这些区域进行了更深入的研究,以确切地了解这些数字的来源。


1.png哪个国家的 Java 开发者最多?

我们进一步研究了拥有最多 Java 开发人员的各个国家,然后调查了为什么这些国家在专业开发中特别喜欢 Java 而不是其他语言。

下图显示了每个国家使用 Java 作为主要语言的开发人员的百分比(用于收集此数据的调查对象最多可以选择 3 种主要语言)。中国韩国 的数值最高,分别约为 51%和 50%。数据来自 2020 年开发者生态系统状况调查

专家分析

Java 在前 6 个国家如此流行的原因可能包括 Java 是免费使用的、政府支持和开源。对于 中国、西班牙巴西 尤其是这样。它是在 中国和印度 进行 Android 移动开发的基础,并且雇佣海外人员用 Java 开发手机应用程序非常普遍,这可能是 印度 使用量达到峰值的原因。德国 的使用率也很高,这可以归因于 Java 在 德国 软件工程师中是最流行的语言,因为多种行业都使用 Java 来构建高度可扩展的应用程序。大多数企业服务都依靠 Java 来驱动应用程序支持日常业务的运行,例如工资单、库存管理、报表等。德国还有一个庞大的金融部门,在本国技术上大量使用 Java,例如交易机器人、零售银行系统以及金融业为了保持竞争所需要的其他应用程序。

我们本以为美国会有很高比例的 Java 用户,但是并没有,这也是很合理的。有大量的技术栈可供选择,而且很多技术公司通常处于这些技术栈的最前沿,因此那里的开发人员可能不需要 Java 的强大功能或稳定性,而是使用能让他们进行快速构建和测试等的语言。

2.pngJava 在开发行业中的位置

根据 2020 年开发者生态系统状况调查,有超过三分之一的专业开发人员将 Java 用作主要语言,而 Java 在专业开发人员当中仍然是仅次于 JavaScript 的第二大主要语言。

专家分析

看到 JavaScript 和 Java 处于领先地位,这并不奇怪,因为它们是成对的:使用 Java 的开发人员经常使用 JavaScript 编写前端和任意快速脚本。由于机器学习的普及,Python 可能排名第三。一般来说,我们希望 Web 成为开发人员生态系统的重要组成部分,因此 JavaScript、HTML 和 CSS 以及 PHP 将始终能拥有稳固的地位。SQL 也会一直存在,因为没有多少东西是不需要某种容量的数据库的。C++ 也是一种坚实的语言,因为它被用于许多嵌入式应用程序中,因此它不会很快在图表中消失。虽然 C# 似乎正在逐渐衰落,但我想如果 Java 比例高,C# 就会低,因为它们在功能上非常相似。至于为什么我认为 Java 在专业发展领域如此之高,原因与之前提到的德国类似。大多数企业的业务服务都依靠 Java 来运行。它不仅仅用于 IT 部门,几乎每个公司,无论是分销、制造还是银行业,都将 IT 服务作为其基础设施的一部分,而这些服务,如工资单或库存管理,通常都是在后端使用 Java 构建的。因此,Java 被这些公司的专业开发人员所大量使用。

3.png用 Java 开发的软件类型

快速浏览一下用 Java 开发的软件类型,应该可以了解它的使用统计信息。根据2020 年开发者生态系统状况调查的结果,Java 使用最流行的领域是 Web 服务,占 52%。

专家分析

看到 Java 在商业智能 / 数据科学 / 机器学习中如此流行,真令人惊讶,因为你可能认为这将是 Python 的领域。其他的就不足为奇了,因为 Web 服务的后端通常是 Java,而且使用 Java 编写业务应用程序也很有意义,因为它们也需要使用后端和数据库。

4.png使用 Java 的热门行业

既然我们知道了为什么这么多专业开发人员使用 Java,那么让我们具体看看 Java 应用于哪些行业。

根据 2020 年开发者生态系统状况调查,Java 程序 主要用于 IT 服务(42%)与金融和金融科技领域(44%),但这并不是说 Java 没有用于其他行业。

专家分析

金融和金融科技领域主要涉及金融交易所、零售银行系统、创建计算引擎以及开发本地定制工具和服务,以使公司在市场上具有竞争力。金融和金融科技几乎都是用 Java 建立的,所以在这里没有什么好惊讶的。IT 服务也是如此,因为许多针对非 IT 公司的薪资系统和库存管理服务都是基于 Java 构建的。其他行业也很有趣。由于 Android 的存在,移动开发的比例可能很高,因此 Java 正以这种方式被使用。大数据和数据分析也非常有趣,因为该行业是由 Python 主导的,但是后端可能会使用 Java 和 JVM 语言。当然构建软件开发工具也可以。JetBrains IDE 目前是用 Java 构建的。尽管其他行业有点神秘,但实际上,了解 Java 在这些行业中的使用方式将非常有趣。

5.pngJava 相关工具

Java 版本

Java 8 仍然是最受欢迎的版本。在使用 Java 作为主要语言的专业开发人员当中,有 75%的人使用 Java 8。基于开发人员在 2020 年开发者生态系统状况调查 中选择的几个版本,下图显示了 Java 版本的分布情况。

专家分析

有几个因素导致了 Java 8 的如此流行。首先,它拥有典型的 Java 开发人员所需要的所有语言,它具有 lambda 和流,并且它是一个很好的易于使用的版本。另外,人们一直不愿意迁移到 Java9。Java9 引入了一些重大的架构更改,人们担心这些更改会破坏他们用 Java 8 构建的应用程序。最重要的是,Oracle 还推出了每两年发布一次的版本,因此并不是所有版本都是长期受支持的,因此 Java 9、Java 10、Java 12 和 Java 13 仅受 6 个月的支持,这可能就是为什么它们都只有这么少用户的原因。Java 13 之所以如此之高,是因为当本调查公布时,它是最新的版本,因此你可以预期,该数字将在几个月后下降。

Java 11 发布于 2018 年,它是长期受支持的最新版本。许多企业仍未迁移到它,因为他们担心超过 Java 9(由于其架构的更改)会破坏一切,而且 Java 11 引入了新的许可和新的订阅,因此它带来了一个新的恐惧:更担心如果使用了错误的版本,以错误的方式使用它,Oracle 会对你进行罚款。许多开发人员没有升级到 Java 11 的最后一个主要因素是,它没有很多令人兴奋的新功能,因此该语言的功能并没有降低升级的风险。Java 17 将是下一个拥有长期支持的版本,并带有许多新功能,但是直接从 Java 8 升级到 Java 17 也会带来一些问题。

我的预测是,我认为下一个长期版本 Java 17 将比上一个 LTS(长期支持版本)Java 11 更受欢迎。不过,作为 Java 17 的准备,这一点我再强调也不为过,建议你先将代码库更新到 Java 11,然后再更新为 Java 17,以避免出现大问题。

6.png流行的应用服务器

在过去的 3 年中,Apache Tomcat 仍然是最受欢迎的应用服务器,而 JBoss EAP 和 WildFly 的使用量却减少了一半。给出的数据来自参加 2018 年 和 2020 年 开发者生态系统调查的所有以 Java 为主要语言的开发人员。

专家分析

Jetty 位居第二,但它确实低得令人惊讶。可能是某些正在使用 Spring Boot 和其他微服务框架的开发人员没有意识到他们到底在使用使用,他们可能在不知不觉中使用了 Tomcat 或 Jetty。

7.png排名前 5 的 Web 框架

在 2018 年,Spring Boot 与 Spring MVC 是一样流行的,到了 2020 年,它变得更加流行。给出的数据来自所有使用 Java 作为主要语言的开发人员。

专家分析

这基本上只是在证实 Spring 拥有市场。几乎可以肯定的是,仍然有人在使用 Struts 1,但它只是用于遗留应用程序。

8.png排名前 5 的分析器

2020 年开发者生态系统状况调查 显示,有 24%的用户使用 VisualVM,而一半的用户则没有使用。给出的数据来自所有使用 Java 作为主要语言的开发人员。

9.png

排名前 5 的 IDE/ 编辑器

2018 年 和 2020 年 的开发者生态系统调查显示,IntelliJ IDEA 的份额从 2018 年的 55%增加到 2020 年的 72%,而其他四个的使用率则有所下降。

专家分析

不过,即使我们对调查结果进行了加权,但我们并不否认这些信息可能会有些偏差,因为这是来自 JetBrains 开发者生态系统状态调查,而 JetBrains 的一个主要产品就是 IntelliJ IDEA。然而,这并不是说这并非完全不合理,就好像我们在其他调查中看到的一样,IntelliJ IDEA 通常是使用最多的 IDE 之一,并且通常拥有约 55-60%的用户份额。VS Code 正在增长,这不是从竞争的角度来看的,而是从缺乏对 IDE 的理解的角度来看的。VS Code 是一个代码编辑器,带有一些你可以在 IDE 中找到的特性,并且可以提供附加功能的扩展。因此,如果人们使用 VS Code 进行开发,则可能意味着开发人员不知道一个功能齐全的 IDE 能给他们什么。在 Web 领域,使用编辑器是可以理解的,因为 Web 开发人员通常使用动态语言,并且经常使用其他工具(例如浏览器插件)来满足他们的需求。但是在 Java 中,特别是在专业的 Java 中,你确实可以从一个与应用程序服务器集成的优秀工具中得到很多东西,你可以真正使用分析、重构等功能。

我们专家的最新消息

我发现有很多对本博客文章数据分析进行删减和编辑的版本,这是我无意间造成的混乱。我想澄清一下我对开发人员和 IDE 评论背后的意图。对我来说,如果开发人员不理解 IntelliJ IDEA 作为一个功能齐全的 IDE 给他们带来了什么,那对我来说就是一个失败,因为这六年来我的工作就是让开发人员了解 IDE(特别是 IntelliJ IDEA)能为你做什么。我强烈地认为,人们不应该因为不了解产品而责备用户或潜在用户。

我个人对 IDE 的观点来自拥有 20 多年 Java 开发经验的 Java 开发人员,他们开发过各种大大小小的 Java 项目。如果没有像 IntelliJ IDEA 这样的 IDE 提供大量的帮助,我无法想象如何创建一个复杂的企业应用程序。我也见过很多开发人员使用 VS Code,并且我完全了解代码编辑器所涵盖的用例。在你的工具箱中总有能容纳多于一种的工具,了解某个工具的优点将有助于我们为正确的工作选择合适的工具。

10.png讨论最多的 Java 工具和其他语言

在 IT 社区中会经常讨论 Java,其中的一个社区就是 Stack Overflow。我们从 “问答”部分 中获取了数据,以找出哪些标签与“ java”最相关。纵轴表示提到 Java 的次数,横轴表示标签出现的总次数。

专家分析

对于那些希望确保自己使用了正确的技术或正寻找适合自己的工具的用户来说,这个图表可能很有用。这些语言很有意思,但这可能是因为人们正在寻找 Java 与其他语言之间的比较。正则表达式是人们苦苦挣扎的一个利基领域,但它能上榜也就不足为奇了。

11.pngJava 社区的热门话题

Java 的讨论

我们分析了 Reddit 上“ java”子版块的帖子,并发现了 Java 用户在 Reddit 上讨论最多的主题。

专家分析

这些正是我期望看到的话题。例如,用 Java 编写代码的人总是会对这种语言是否仍然有需求感兴趣,毕竟,这种语言还在发展。我们刚刚庆祝了 Java 诞生 25 周年,因此人们希望检查它是否过时了,以及它是否仍然有效。特别是,如果他们刚从大学毕业,还不知道他们所学的语言是否能为他们提供工作机会。在容器中部署 Java 是一个非常热门的话题,包括我在内,这是每个人都想知道的东西,但几乎找不到任何相关信息。我对性能优化这个主题并不感到惊讶,尽管我认为这个主题有点多余,因为大多数应用程序实际上并不需要开发人员来进行优化,尽管许多开发人员认为这是一项重要的职业技能。使后端和前端协同工作也非常复杂,我可以想到有很多关于这方面的问题。

12.png

原文链接:

https://blog.jetbrains.com/idea/2020/09/a-picture-of-java-in-2020/



跳来跳去,程序员到底去大公司还是小公司?

技术交流大兴 发表了文章 • 0 个评论 • 93 次浏览 • 2020-10-10 18:30 • 来自相关话题

职场生涯总会面临着选择,尤其对我们这些 IT 人来说,跳槽的频率应该是所有行业中相当大的了。那么我们跳来跳去,究竟该选择什么样的公司 ?大 or 小 。工作三年多了,经历一大一小,最近也面试了不少家公司,形态各异,说说自己的感受想法。在小公司中,给我个人的印象... ...查看全部

untitled.png

职场生涯总会面临着选择,尤其对我们这些 IT 人来说,跳槽的频率应该是所有行业中相当大的了。那么我们跳来跳去,究竟该选择什么样的公司 ?大 or 小 。

工作三年多了,经历一大一小,最近也面试了不少家公司,形态各异,说说自己的感受想法。

在小公司中,给我个人的印象大多数环境都不怎么样。定义下这个小公司规模吧,在几人到几十人吧,反正不会超过100人。

亲历一家小公司, 面试见过数家小型公司。我觉得大概分两种:

1.真正的黑穷丑

入职原因:实在没地方去了,毕业什么也不会,来做苦工吧

缺点:加班是家常便饭、工资少的可怜、福利基本没有,事事都要你干

优点:锻炼你顽强的意志力、培养男人的愤怒血性,当然干的多了能力自然也会有提升,不过如果没有牛人带且自己也不是特强的话,你的视野应该是比较窄的

2.有稳定业务、公司盈利还不错,待遇也可以媲美大公司

缺点:还是个人视野的问题,如果你个人能力很好,不是野心很大,在小公司也不错

优点:至少福利待遇不会差,环境也还可以,公司小自己做的贡献领导会看到,做个2,3年可能就是公司的主干力量了,有成就感。

说说自己的第一家公司,那个小公司

自己毕业时选择的是这家小公司,说选择当时是有对比,而最终决定去这家小公司的原因是他给开了3k的工资,比其他两个相对大的公司多,于是就去了,虽然环境不怎么样,自己也忍了,觉得应该锻炼机会很多吧,有家公司环境着实不错,可是帝都1600的工资实在觉得跌面儿。

正像我说的第2种小公司一样,老板有自己的关系公司每年的盈利还不错,几十人的小公司过的也还算舒服。工资每年都会涨,没用自己提过,基本在一年1k左右,毕业刚去的那年发了5k的年终奖,欣喜的不亦乐乎。

在公司的工作就是做一些小项目,很少加班,开始有人带,而后就是自己做项目,整个项目的方方面面,再后来还要带一些刚毕业的小弟弟,实在不敢以师傅挂名,羞愧不敢当,觉得自己的水平不够,于是考虑到在该公司的状况也就如此了,自己又不是视野很宽知道学什么的主,于是有了离开的打算,想去看看国外的月亮。

没见过国外的月亮,都会觉得外面的月亮是更圆的。尽管工作2年的时候工资翻了一倍,那年的年终奖也拿到2w多的地步,老板器重的情况下,还是选择了了离开。

觉得外面的世界很精彩,自己需要出去看看,就这样离开了,来到了一家规模还比较大的互联网公司,虽然工资只比原来多了1k,还是去了,觉得神秘的大公司应该可以学习到不少的东西吧。

很庆幸,刚毕业没有遇见第一种小公司,一些脏乱差,到处摆满东西的公司在后来的面试时还真是见过几个。

一个插曲:一个什么外包公司要我去面试,进去后一看里面安了很多挡板,临时搭的那种,我以为公司发展过来的小分部,随后了解说这是公司总部,汗颜。

来到了大公司

虽然钱没多挣(也许还不如以前的多),但一下子觉得自己牛逼了不少,因为自己的公司耳熟能详啊,可以和别人吹牛逼,也可以给自己的职业生涯贴贴金。

干净的办公环境,每过一会儿就有人清理的卫生间,正版的操作系统、应用软件,公司项目用的新技术,一切的一切都是新鲜的,就像一个村儿逼来到了城里看见了摩天大厦,豁然开朗。周围人也都是4,5年工作经验的牛人……

也就是半年吧,新鲜感过了,也没什么了。唯一感觉的就是觉得工作无聊,整天维护着那么一个小项目,有时很长时间都不知道做什么,也许是自己的问题吧,但是我确定的是这不是我想要的,跟我想的不一样。

不过在该公司的一年多时间里,技术上有一定的提高、见识也增长了不少,但是更大的变化是自己的思想发生了很大的改变。

以前觉得自己是一个.net程序员,就像园子里曾经有人说,这个叫法很蹩脚很奇怪,确实是这样,我们为什么要把自己定义为一个xx程序员?而我们只是一个程序员啊,写代码的程序员,不管是java、c#、php、python、javascript…. 这是一个重要改变。

一直在想,我追求的所谓大公司,到底追求的是什么?

离开第一家小公司想要追求的东西,想要有人带,有高手指导,而这只不过是自己能力的欠缺与知识获取方面能力的不足罢了。

当我们自己这两方面足够强大的时候,我们就成为了高手,不再需要别人的指导,你追求的大公司也就成为了一个空壳。

所以我觉得,大公司、小公司都无所谓,首先我们要让自己牛逼,或者知道怎样牛逼起来,然后再有施展技能的平台就够了,大、小只是一个壳罢了,问题的根源在于你是否能够牛逼起来!


Python 之父 Guido van Rossum 正式加入微软搞开源!

技术交流王叫兽 发表了文章 • 0 个评论 • 42 次浏览 • 2020-11-13 10:39 • 来自相关话题

今天,Python 之父 Guido van Rossum 在 Twitter 上正式宣布,退休太无聊,如今加入了微软开发者部门。Guido van Rossum 去年宣布退出 Python 核心决策层事实上,近几年来,随着人工智能的飞速发展,Python 横... ...查看全部

今天,Python 之父 Guido van Rossum 在 Twitter 上正式宣布,退休太无聊,如今加入了微软开发者部门。在这里插入图片描述

Guido van Rossum 去年宣布退出 Python 核心决策层

事实上,近几年来,随着人工智能的飞速发展,Python 横扫各大编程语言榜单,成为最受欢迎的程序设计语言之一。作为 Python 的创建者,Guido van Rossum 一边致力于 Python 社区维护,一边在 Dropbox 公司任职六年半后,突然于去年 10 月宣布将要退休,退出 Python 核心决策层。

在这里插入图片描述

彼时,Guido van Rossum 发布邮件表示,“我不想再为 PEP(Python 改进提案)[ PEP 572 ] 如此劳心劳力了,(而且尽管我在进行着如此艰难的战斗)却发现仍然有很多人不满意我所做出的决定。”

而后,被称为 “仁慈的终生独裁者”(BDFL,Benevolent Dictator for Life)的 Guido Van Rossum 在接受媒体采访时,回应退出的缘由:

所谓的终生和独裁都仅仅是玩笑。实际上,最近十年,退休的念头都在我脑海里徘徊。

我年龄已经不小了,身体也有一些问题。作为 Python 社区的主要负责人,我需要一遍又一遍地去教社区的其他成员如何开展工作,同时需要一遍又一遍地向 Python 新人解释 Python 的语言哲学,这样超负荷的工作让我的健康状况更为恶化。

事情的引爆点在于一个颇具争议的 Python 改进提案(PEP 572),当我接受这个提案之后,Twitter 等社交媒体上出现了一些中伤我的评论。而更为心寒的是,这些评论居然大多来自 Python 的核心成员,我对他们失望至极!

退休太无聊

如今看来,大佬的退休并不意味真正的离开。

Guido van Rossum 最新表示,退休太无聊,在微软,他将致力于“确保更好地使用 Python(不仅限于 Windows)。”

对此,一个微软发言人表示,该公司也没有其他细节可分享,但证实了 Guido van Rossum 确实已经加入了微软。“我们很高兴能将他加入开发者部门。微软致力于为 Python 社区做出贡献,并与之一起成长,而 Guido 的入职就是这一承诺的体现。”

同时,在该条 Twitter 下方,大神 Anders Hejlsberg(Delphi、C#、Typescript 发明人)表示期待与 Guido van Rossum 一起工作。

Python 之父 Guido van Rossum

上世纪 80 年代末,Guido 因对已有编程语言失望,决心开发一门易用且功能强大的新语言 Python。对此,他仅用了 3 个月的时间就开发了 Python 原型。

在 20 世纪 90 年代中期,他继续在美国国家标准技术研究院及之后的多家公司中积极从事该语言的工作,包括担任 Python Labs 的主管等。

在去 Dropbox 之前,他曾在 Google 工作,从 2005 年到 2012 年。在那里,他开发了内部代码审查工具 Mondrian,并应用于 Google App Engine。

如今,Guido van Rossum 选择加入微软,据悉,与 Typescript/C# 创始人 Anders,VS Code/Eclipse 创始人 Eric,Linux GNOME 作者Miguel 共同任职于微软全球资深副总裁潘正磊团队中,至于要做什么,其表示:

我认为退休很无聊,因此加入了 Microsoft 开发人员部门。做什么?选择太多了!但这肯定会使使用 Python 更好(而不仅仅是在Windows)。这里有很多开源。

同时,在微软深度拥抱开源的当下,Guido van Rossum 的加入,也如虎添翼。我们也将共同期待 Guido van Rossum 未来的发展。


融云 IM SDK 转 AndroidX

融云集成徐凤年 发表了文章 • 0 个评论 • 44 次浏览 • 2020-11-06 16:07 • 来自相关话题

最近公司项目要开发 IM 即时通信功能, 所以采用了融云即时通信 SDK。 但在集成的时候很快就发现了一个问题. 由于我们的工程是 AndroidX 的, 集成 Module 之后结果报错. 但是, 在融云官网却没有找到 Androidx 版本的 SDK.然后... ...查看全部

微信截图_20201106154036.png

最近公司项目要开发 IM 即时通信功能, 所以采用了融云即时通信 SDK。 但在集成的时候很快就发现了一个问题. 由于我们的工程是 AndroidX 的, 集成 Module 之后结果报错. 但是, 在融云官网却没有找到 Androidx 版本的 SDK.

然后自己通过查资料,然后在 gradle.properties 里的配置添加, 然后同步编译.

android.useAndroidX = trueandroid.enableJetifier = true

结果还是报错. 无奈之下找融云技术支持咨询一下. 技术支持同学告知, 如果工程原来就是 Androidx, 则需要先把 android.useAndroidX 和 android.enableJetifier 设置为 false, 同步编译一遍, 然后再设置成 true, 然后再同步编译, 这样就正确了。自己试了一下结果真的可以. 这可能是 Android Studio 的一个 bug 吧.

最后工程中代码中会提示不兼容类型的错误,但不影响编译运行。

技术支持同学也告知另一种更简单的方法, 就是直接使用容云官网提供的 maven 远程依赖方式使用 SDK 不会出现不兼容的问题, 亲测是可以的. 如果有遇到同样问题的童鞋可直接使用 maven 远程依赖库进行集成.


带你实现女朋友欲罢不能的 App

技术交流徐凤年 发表了文章 • 0 个评论 • 39 次浏览 • 2020-11-06 16:07 • 来自相关话题

前言带你实现女朋友欲罢不能的 App需求需要日记本,甜言蜜语要记录需要只能和 ta 聊天模块需要可以记录关键日期,避免忘记送命0202年了,Android开发大都应该是老油条了把。这太简单,我们开始动手。我知道没图是骗不到人的。先放图,大家看一下最终实现的效果... ...查看全部

前言

带你实现女朋友欲罢不能的 App

需求

  1. 需要日记本,甜言蜜语要记录

  2. 需要只能和 ta 聊天模块

  3. 需要可以记录关键日期,避免忘记送命
    0202年了,Android开发大都应该是老油条了把。这太简单,我们开始动手。
    我知道没图是骗不到人的。先放图,大家看一下最终实现的效果。
    banner.jpg

    即时通讯部分

    使用了融云 sdk 集成了单聊部分
    配置布局文件
    这是您的会话列表 Activity 对应的布局文件:conversationlist.xml。注意 android:name 固定为融云的 ConversationListFragment。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <fragment        android:id="@+id/conversationlist"        android:name="io.rong.imkit.fragment.ConversationListFragment"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

新建 Activity

public class ConversationListActivity extends FragmentActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.conversationlist);        FragmentManager fragmentManage = getSupportFragmentManager();        ConversationListFragment fragement = (ConversationListFragment) fragmentManage.findFragmentById(R.id.conversationlist);        Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()            .appendPath("conversationlist")            .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")             .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.APP_PUBLIC_SERVICE.getName(), "false")            .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "true")            .build();        fragement.setUri(uri);    }  }
<!--会话列表--><activity    android:name="io.rong.fast.activity.ConversationListActivity"    android:screenOrientation="portrait"    android:windowSoftInputMode="stateHidden|adjustResize">    <intent-filter>        <action android:name="android.intent.action.VIEW" />        <category android:name="android.intent.category.DEFAULT" />        <data            android:host="io.rong.fast"            android:pathPrefix="/conversationlist"            android:scheme="rong" />    </intent-filter></activity>

其他部分参考
融云官网:https://www.rongcloud.cn/
文档频道:https://docs.rongcloud.cn/v4

纪念日部分

日历控件:https://juejin.im/post/6844903512007000077
其他部分如若有人需要,会尽快传到 github 。
github:https://github.com/yanxiame/rongcloud/tree/loverschat


关于融云聊天室KV 值的正确使用

融云集成徐凤年 发表了文章 • 0 个评论 • 44 次浏览 • 2020-11-06 16:07 • 来自相关话题

在使用融云集成即时通讯的过程中,根据产品业务逻辑,我们使用了融云聊天室场景,因为我们主要做的是直播聊天室的业务;在使用聊天室的过程中,了解到融云这边是有针对聊天室属性做处理的,这样的话,更加方便产品的某些功能点的实现,比如说 人数的动态变化等等;现就我这边了解... ...查看全部

微信截图_20201106154411.png

在使用融云集成即时通讯的过程中,根据产品业务逻辑,我们使用了融云聊天室场景,因为我们主要做的是直播聊天室的业务;在使用聊天室的过程中,了解到融云这边是有针对聊天室属性做处理的,这样的话,更加方便产品的某些功能点的实现,比如说 人数的动态变化等等;

现就我这边了解到的聊天室的KV 对大家做一个说明,增进对KV 使用的了解; 首先,要获取聊天室的属性,我们当然应该加入聊天室,加入聊天室的方式如下所示:

 RongIM.getInstance().joinChatRoom(roomId, 20, new RongIMClient.OperationCallback() {
        @Override
        public void onSuccess() {
        }
        @Override
        public void onError(RongIMClient.ErrorCode errorCode) {
        }
    });

以上方法无需多言,调用即可加入聊天室,具体参数文档可以参考融云文档

当然,要获取聊天室属性获取之前,肯定要知道如何设置聊天室属性的,以下方式主要展示客户端的设置方式:

 RongIMClient.getInstance().setChatRoomEntry(chatRoomId, key, value, sendNotification, isAutoDel, notificationExtra, new RongIMClient.OperationCallback() {
/**
 * 成功回调
 */
@Override
public void onSuccess() {
}
/**
 * 失败回调
 * @param errorCode 错误码
 */
@Override
public void onError(RongIMClient.ErrorCode errorCode) {
}

接下来就是获取的方式了,这块是我在集成过程中花费时间比较久的,在获取之前,需要先了解融云对于聊天室KV 的整体流程设置:

  • 加入聊天室之后,通过设置的监听  setKVStatusListener 来获取到服务KV 的变化,然后在收到变化之后,在调用 getChatRoomEntry 来获取KV 值即可  。

    注意:前提条件是设置监听获取到KV 变化之后,才去获取,因为这个变化是服务发出的,也就是说这是一个通知状态;

    监听的设置方式:

 RongIMClient.getInstance().setKVStatusListener(new RongIMClient.KVStatusListener() {
     @Override
     public void onChatRoomKVSync(String roomId) {
     }
     @Override
     public void onChatRoomKVUpdate(String roomId, Map<String, String> chatRoomKvMap) {
     }
     @Override
     public void onChatRoomKVRemove(String roomId, Map<String, String> chatRoomKvMap) {
     }
 });

当服务的KV 发送变化时候,会在 onChatRoomKVUpdate 中回调到的,回调中的Map 就是变化得KV 值,当然可以用户主动调用来进行获取,方式如下:

  RongIMClient.getInstance().getAllChatRoomEntries(roomId, new RongIMClient.ResultCallback<Map<String, String>>() {
        @Override
        public void onSuccess(Map<String, String> stringStringMap) {
        }
        @Override
        public void onError(RongIMClient.ErrorCode e) {
        }
    });

通过以上步骤即可完成聊天室属性的设置,以及获取;

自定义消息 包含 list 数组

技术交流徐凤年 发表了文章 • 0 个评论 • 34 次浏览 • 2020-11-06 16:07 • 来自相关话题

公司产品越来越复杂,业务线也不断的增加,项目中聊天模块使用了融云的 sdk ,但是 sdk 中自带的消息类型有限,不能满足产品需要的多张图片布局的消息类型,只能自定义一个,但是发现没有包含 list 的消息例子,实现起来有点繁琐,这边给大家参考下。————消息... ...查看全部

微信截图_20201106154952.png

公司产品越来越复杂,业务线也不断的增加,项目中聊天模块使用了融云的 sdk ,但是 sdk 中自带的消息类型有限,不能满足产品需要的多张图片布局的消息类型,只能自定义一个,但是发现没有包含 list 的消息例子,实现起来有点繁琐,这边给大家参考下。
————消息体—————

  1. 新建一自定义消息类,继承 MessageContent

2.实现 encode() 方法,该方法的功能是将消息属性封装成 json 串,再将 json 串转成 byte 数组,该方法会在发消息时调用
注意:要在这个方法里面加上这句话用来携带用户信息
if (getJSONUserInfo() != null){
               jsonObj.putOpt(“user”, getJSONUserInfo());
           }

3.覆盖父类的 MessageContent(byte[] data) 构造方法,该方法将对收到的消息进行解析,先由 byte 转成 json 字符串,再将 json 中内容取出赋值给消息属性。
注意:要在这个方法里面加上这句话用来解析携带用户信息
 if (jsonObj.has(“user”))
               setUserInfo(parseJsonToUserInfo(jsonObj.getJSONObject(“user”)));

4.MessageContent 已实现 Parcelable 接口,自定义消息类也需要实现 Parcelable

5.增加注解信息 :注解名:MessageTag ;属性:value ,flag; value 即 ObjectName 是消息的唯一标识不可以重复,
开发者命名时不能以 RC 开头,避免和融云内置消息冲突;flag 是用来定义消息的可操作状态。
flag 值如下表:
枚举值 说明
MessageTag.NONE 为空值,不表示任何意义,发送的自定义消息不会在会话页面和会话列表中展示。
MessageTag.ISCOUNTED 表示客户端收到消息后,要进行未读消息计数(未读消息数增加 1),所有内容型消息都应该设置此值。非内容类消息暂不支持消息计数。
MessageTag.ISPERSISTED 表示客户端收到消息后,要进行存储,并在之后可以通过接口查询,存储后会在会话界面中显示。
MessageTag.STATUS 在本地不存储,不计入未读数,并且如果对方不在线,服务器会直接丢弃该消息,对方如果之后再上线也不会再收到此消息(聊天室类型除外,此类消息聊天室会视为普通消息)。

6.自定义消息应在 init 后注册 RongIM.registerMessageType(CustomizeMessage.class);
—————-自定义消息展示————-

package cn.rongcloud.demo;

import android.os.Parcel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import io.rong.common.ParcelUtils;
import io.rong.common.RLog;
import io.rong.imlib.MessageTag;
import io.rong.imlib.model.MessageContent;

@MessageTag(value = "sendGoodsLocal", flag = MessageTag.ISPERSISTED)
public class SendGoodsLocalMessage extends MessageContent {
    private String content;
    private String id;
    private int typeid;
    private List<String> img =new ArrayList<>();
    private SendGoodsLocalMessage() {
    }

    public SendGoodsLocalMessage(Parcel in) {
        this.content = ParcelUtils.readFromParcel(in);
        this.id = ParcelUtils.readFromParcel(in);
        this.typeid = ParcelUtils.readIntFromParcel(in);
        this.img = ParcelUtils.readListFromParcel(in,String.class);
    }

    public SendGoodsLocalMessage(byte[] data) {
        String jsonStr = null;
        try {
            jsonStr = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException var5) {
            RLog.e("GroupNotificationMessage", "UnsupportedEncodingException ", var5);
        }

        try {
            JSONObject jsonObj = new JSONObject(jsonStr);
            this.setContent(jsonObj.optString("content"));
            this.setId(jsonObj.optString("id"));
            this.setTypeid(jsonObj.optInt("typeid"));
            JSONArray jsonArray = jsonObj.optJSONArray("img");
            List<String> imgList = new ArrayList<>();
            for (int i = 0; i < jsonArray.length(); i++) {
                imgList.add((String) jsonArray.get(i));
            }
            setImg(imgList);
//            this.setImg();
        } catch (JSONException var4) {
            RLog.e("GroupNotificationMessage", "JSONException " + var4.getMessage());
        }

    }

    public static final Creator<SendGoodsLocalMessage> CREATOR = new Creator<SendGoodsLocalMessage>() {
        public SendGoodsLocalMessage createFromParcel(Parcel source) {
            return new SendGoodsLocalMessage(source);
        }

        public SendGoodsLocalMessage[] newArray(int size) {
            return new SendGoodsLocalMessage[size];
        }
    };

    public static SendGoodsLocalMessage obtain(String content, String id, int typeid, List<String> img) {
        SendGoodsLocalMessage obj = new SendGoodsLocalMessage();
        obj.content = content;
        obj.id = id;
        obj.typeid = typeid;
        obj.img = img;
        return obj;
    }

    public String getContent() {
        return content;
    }

    public List<String> getImg() {
        return img;
    }

    public void setImg(List<String> img) {
        this.img = img;
    }

    public int getTypeid() {
        return typeid;
    }

    public String getId() {
        return id;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setTypeid(int typeid) {
        this.typeid = typeid;
    }

    @Override
    public byte[] encode() {
        JSONObject jsonObj = new JSONObject();
        try {
            jsonObj.put("content", this.content);
            jsonObj.put("id", this.id);
            jsonObj.put("typeid", this.typeid);

            JSONArray jsonArray = new JSONArray();
            for (String name : img) {
                jsonArray.put(name);
            }
            jsonObj.put("img", jsonArray);

        } catch (JSONException var4) {
            RLog.e("GroupNotificationMessage", "JSONException " + var4.getMessage());
        }
        try {
            return jsonObj.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException var3) {
            RLog.e("GroupNotificationMessage", "UnsupportedEncodingException ", var3);
            return null;
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        ParcelUtils.writeToParcel(dest, this.content);
        ParcelUtils.writeToParcel(dest, this.id);
        ParcelUtils.writeToParcel(dest, this.typeid);
        ParcelUtils.writeToParcel(dest, this.img);
    }
}
package cn.rongcloud.demo;


import android.content.Context;
import android.content.Intent;
import android.text.Spannable;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import com.bumptech.glide.Glide;

import io.rong.imkit.model.ProviderTag;
import io.rong.imkit.model.UIMessage;
import io.rong.imkit.widget.provider.IContainerItemProvider;

@ProviderTag(
        messageContent = SendGoodsLocalMessage.class,
        showPortrait = false,
        centerInHorizontal = true,
        showProgress = false,
        showSummaryWithName = false
)
public class SendGoodsLocalProvider extends IContainerItemProvider.MessageProvider<SendGoodsLocalMessage> {

    @Override
    public void bindView(View v, int i, SendGoodsLocalMessage mSendGoodsLocalMessage, UIMessage uiMessage) {
        ViewHolder holder = (ViewHolder) v.getTag();
        holder.tvGoodsName.setText(mSendGoodsLocalMessage.getContent());
        Glide.with(v.getContext()).load(mSendGoodsLocalMessage.getImg().get(0)).centerCrop().into(holder.ivCover);
    }

    @Override
    public Spannable getContentSummary(Context context, SendGoodsLocalMessage message) {
        if (message == null) {
            return null;
        }
        return new SpannableString(message.getContent());
    }


    @Override
    public String getPushContent(Context context, UIMessage message) {
        return super.getPushContent(context, message);
    }

    @Override
    public Spannable getContentSummary(SendGoodsLocalMessage mSendGoodsLocalMessage) {
        return null;
    }

    @Override
    public void onItemClick(View view, int i, SendGoodsLocalMessage mSendGoodsLocalMessage, UIMessage uiMessage) {

    }

    @Override
    public View newView(Context context, ViewGroup viewGroup) {
        View view = LayoutInflater.from(context).inflate(R.layout.rc_send_goods_message, null);
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.tvGoodsName = view.findViewById(R.id.tvGoodsName);
        viewHolder.tvSend = view.findViewById(R.id.tvSend);
        viewHolder.ivCover = view.findViewById(R.id.ivCover);
        view.setTag(viewHolder);
        return view;
    }
    private static class ViewHolder {
        TextView tvGoodsName,tvSend;
        ImageView ivCover;
        private ViewHolder() {
        }
    }
}

大家可以当一个参考。


Flutter 集成融云 sdk

技术交流徐凤年 发表了文章 • 0 个评论 • 43 次浏览 • 2020-11-06 16:07 • 来自相关话题

前言1.集成 flutter 融云 sdk ,需要一个稳定的 flutter 环境,能正常的创建和运行项目。2.前期准备融云官网申请开发者账号通过管理后台的 “基本信息”->”App Key” 获取 AppKey3.通过管理后台的 “IM 服务”—>... ...查看全部

前言

1.集成 flutter 融云 sdk ,需要一个稳定的 flutter 环境,能正常的创建和运行项目。
2.前期准备融云官网申请开发者账号
通过管理后台的 “基本信息”->”App Key” 获取 AppKey
3.通过管理后台的 “IM 服务”—>”API 调用”->”用户服务”->”获取 Token”,通过用户 id 获取 IMToken
4.我知道没图是骗不到人的。先放图,大家看一下最终实现的效果。
BsvRVU.jpg

集成 sdk

依赖 IM Flutter plugin在项目的 pubspec.yaml 中写如下依赖。

dependencies:
  flutter:
    sdk: flutter
rongcloud_im_plugin: ^4.0.3
  1. 然后在项目路径执行 flutter packages get 来下载 Flutter Plugin。

  2. 我们写 2 个 button 和 2 个 text ,分别用来实现 init 和 connect 的事件和状态。

  3. 初始化 SDK

RongIMClient.init(RongAppKey);

4.连接 IM

RongIMClient.connect(RongIMToken, (int code, String userId) {
print('connect result ' + code.toString());
EventBus.instance.commit(EventKeys.UpdateNotificationQuietStatus, {});
if (code == 31004 || code == 12) {
Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute(builder: (context) => new LoginPage()), (route) => route == null);
} else if (code == 0) {
print("connect userId" + userId);
// 连接成功后打开数据库
// _initUserInfoCache();
}

全部代码参考

import 'package:flutter/material.dart';
import 'package:rongcloud_im_plugin/rongcloud_im_plugin.dart' as prefix;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _isInit ;
  var _isConnect ;
  void _init() {
    setState(() {
      prefix.RongIMClient.init("pvxdm17jpof6r");
      _isInit="已经初始化";
    });
  }
  void _connect() {
    setState(() {
      prefix.RongIMClient.connect("rbdI/5jrPxR4aQ2078HhWnHte7+VrAhsnSjOcYQ3SKOCXhodQlcZYZ5acv4syCtN0dsYRNvxZh44fo4VR5s+6A==", (code, userId){
        if(code == 0 ){
          _isConnect="连接成功";
        }else{
          _isConnect="连接失败";
        }
      });
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '$_isInit',
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              '$_isConnect',
              style: Theme.of(context).textTheme.headline4,
            ),
            MaterialButton(
              minWidth: 250.0,
              onPressed: () {_init();},
              colorBrightness: Brightness.dark,
              color: Colors.deepPurpleAccent,
              elevation: 20.0,
              splashColor: Colors.green,
              //highlightColor: Colors.red,
              highlightElevation: 1.0,
              child: Text("初始化"),
            ),
            MaterialButton(
              minWidth: 250.0,
              onPressed: () {_connect();},
              colorBrightness: Brightness.dark,
              color: Colors.deepPurpleAccent,
              elevation: 20.0,
              splashColor: Colors.green,
              //highlightColor: Colors.red,
              highlightElevation: 1.0,
              child: Text("连接"),
            ),
          ],
        ),
      ),
    );
  }
}


如果再给我一次机会,我希望我从未学过编程

技术交流徐凤年 发表了文章 • 0 个评论 • 31 次浏览 • 2020-11-04 14:39 • 来自相关话题

我是一名程序员。你可能会觉得我是专业的软件工程师,但实际上,软件工程不只是一个专业,还是一种生活方式。连帽衫、乒乓球、吃不完的零食和苏打水……都是这种生活的一部分。但虽然这个职业可以给人带来那么多回报,我还是要坦白一件事:有时我希望自己从来没有学过编程。怪癖自... ...查看全部

我是一名程序员。你可能会觉得我是专业的软件工程师,但实际上,软件工程不只是一个专业,还是一种生活方式。连帽衫、乒乓球、吃不完的零食和苏打水……都是这种生活的一部分。但虽然这个职业可以给人带来那么多回报,我还是要坦白一件事:

有时我希望自己从来没有学过编程。

怪癖

自从我开始学习编程以来,就再也不能像以前那样轻松地浏览网页了。我无法再平静地接受在各种网站上遇到的各种 bug。每当有奇怪的事情发生时,我的好奇心就上了头,然后就会打开浏览器开发工具开始调试网页。

尝试提交表单时出现加密错误消息?看到这样的错误,我会深入 JavaScript 控制台,查找错误消息,深入研究源代码,并仔细观察进进出出的网络请求。页面 UI 看起来有些过时,或者页面布局很漂亮?不管怎样,我都会调整浏览器窗口大小,检查页面响应屏幕尺寸的能力。什么?你竟然选择了 Comic Sans 字体?我可能永远不会再使用你或你们公司的产品了。

微信图片_20201104143349.jpg

请不要使用 ComicSans

职业生涯

觉得我的这些浏览习惯很怪异吗?这还不算啥,我和其他软件工程师的对话会让你印象更深刻的。总体而言,工程师往往固执己见。我们的血液中流淌着迂腐的基因。你喜欢使用空格还是 tabs 缩进代码?你更喜欢 Vim 还是 Emacs?Chrome 还是 Firefox?

聪明点的人会问到,这些对话“真的重要吗?”。Bikeshedding(在琐碎细节上浪费时间)是确实存在的现象,大家都需要经常反省。

微信图片_20201104143403.jpg

xkcd——真正的程序员

随着越来越多的公司采用敏捷方法,我们还得时常考虑在 Waterfall、Scrum 或 Kanban 开发生命周期之间权衡取舍。我们所有人都喜欢鄙视 Waterfall,毕竟这是老式的低效率公司所使用的遗留品。但是 Scrum 与看板之战还在继续。

你竟然是 Scrum 的信徒?我敢打赌,你为了满足那些 time box 会仓促提交混乱的代码,才能在冲刺结束之前赶上假想的时限。

微信图片_20201104143416.jpg

说到敏捷,故事的重点在哪里?时间尺度?努力?复杂性?风险?这些都有?你我可能会花费几小时时间来争论每个定义的优缺点,最后还是无法达成共识。

在某些时候,这种争论可能会演变为更多的 bikeshedding,但能够相互理解和有效沟通是至关重要的,其中就包括了对我们日常使用的术语达成共识。

前端开发带来的争论又是数不清的,其中最典型的是:“我们要到什么时候才会放弃对 Internet Explorer 的支持?”我必须在“讨厌 Internet Explorer,想要放弃它”和了解还在用它的客户需求之间找到完美的平衡点。

微信图片_20201104143428.jpg

持续学习

持续学习是每一位开发者必备的能力,因为技术形势日新月异。每月都有成百上千的新库和框架发布。JavaScript 倦怠不是什么幻觉,“学不动了”也不仅仅是调侃。

我得花一天的时间配置 Webpack、Rollup 和 Babel 以使用最新的 ES6+ 语法,而旁人听我这么说就像在听天书。Angular 和 AngularJS 截然不同?LitElement、Svelte 和 Stencil 似乎是很有前途的 Web 组件解决方案?Deno 可能是下一个 Node?听着都像是谜语。

当有人问我做什么工作时,我总会蹦出来一堆术语:“我通常使用前端技术,例如 HTML、CSS 和 JS。有时我必须使用 PHP 或 SQL,但我更多是 MEAN/MERN 栈开发人员。有时我使用 Heroku 之类的 PaaS 技术,还有时我会使用 AWS 或 GCP 之类的 IaaS 提供商。”

微信图片_20201104143437.jpg

个人生活

在业余时间里,我读的书干货十足,例如《干净代码》《重构》和《领域驱动设计》。我不是在看教科书,就是在阅读里面写着可疑建议的文章,或观看一些编程教程。关于编程的播客更能吸引人,这样我就能在路上听某人谈论写代码的方法,然后我又可以花一天时间谈相关话题了。

除了在线获取内容外,软件工程师还会花费大量个人时间来在网上创建内容。我个人的兴趣是构建简单的应用和游戏,其实没人看得到。这是浪费时间吗?也许是吧,但的确挺有意思的。


微信图片_20201104143447.jpg企业 BS 生成器应用

事实是

可事实是,编程给了我创造和创新的机会。它帮助我将创意变为现实,让我几乎从零开始构筑了很多东西。软件工程使我能够解决有趣而艰巨的挑战,理想情况下还能让人们的生活更轻松一些。编程使我的思维更具逻辑性。编程让我有机会不断学习,我还能以编程为职业获取薪水!

事实是,我喜欢编程。

参考阅读

https://hackernoon.com/i-wish-i-never-learned-to-code-7a1m3wwx

未来 10 年,软件开发涨工资的 8 个 技术发展趋势

技术交流王叫兽 发表了文章 • 1 个评论 • 59 次浏览 • 2020-10-20 16:13 • 来自相关话题

英文 | https://medium.com/better-programming/software-developer-trends-of-2020-and-beyond-d1b955bc46b8     &nb... ...查看全部
英文 | https://medium.com/better-programming/software-developer-trends-of-2020-and-beyond-d1b955bc46b8
 
 


 
新的一个十年来到,随之而来的是对技术变革和趋势的兴奋之潮。软件开发已成为世界几乎每个部门不可或缺的一部分,因此软件开发的发展和变化对我们的生活产生了巨大影响。尽管我们无法始终准确地预测技术的发展前景,但我们仍有望在新的十年中延续一些趋势。
 

 
以下是我们预测并讨论的在未来10年里软件开发技术的8个开发趋势。
 


 



1、人工智能将继续占主导地位


尽管人工智能已经存在了很多年,但它每年都在不断增长和增强,成为全球许多技术的基础。开发人员预测,随着越来越多的行业在基础架构中采用AI,人工智能将继续占主导地位。
 
2020年的最大趋势表明,医疗保健,教育,旅游行业和社交媒体将使用AI来提供个性化的体验,帮助和预测服务。人工智能将成为整个行业新的竞争优势,改变我们对人类参与和资源的思考方式。深度学习框架Tensorflow 2.0预计将主导市场。
 


 

2、Python预计会随着AI和Ml的发展而崛起


 


 
从ML研究到视频游戏开发再到Web开发,Python一直被证明是一种流行且广受欢迎的语言。由于ML和AI的发展正在上升,因此预计Python将在这种稳定的增长和普及中继续发展,特别是对于令人印象深刻的创新,包括ML驱动的聊天机器人。
 
尽管“增长最快”语言的概念可能很难确定,但数据表明Python可能是块不错的蛋糕。Python不仅用于各种流行领域和工作,而且入门门槛低,并且由新一代开发人员培育而成的支持社区。
 

 


 

3、5G可能是为开发人员打开大门的下一个重要物种


 
5G将于2020年进入市场。这个令人兴奋,更快的网络带来了开发人员需要解决的新问题。尽管存在诸多弊端和争议,但5G仍有可能革新手持设备,并为开发人员进入分布式技术的底层打开大门。
 
它为开发人员提供了开发更强大的应用程序和增强现实功能的机会。总体而言,预计5G将改变整个世界-从为智慧城市提供动力,到改善交通系统,再到增加网络扩展能力。
 
当然,5G的处理能力还带来了开发人员必须解决的问题,例如
  最近对天气预报技术的关注
 
  对覆盖范围不佳的吐槽
  。不管面临的挑战如何,该技术都是有前途的,值得学习投资。
 

 

 


 

4、边缘和云计算的使用预计会上升

与5G一同出现的还有
  边缘计算
  的潜力:一种分散式计算基础架构。边缘计算的高度分布式模型可能有助于克服云计算的缺点。这些发展可能是计算和工业的未来。
 
事实证明,云计算对于公司基础架构至关重要,并且随着网络安全问题的持续存在,各行各业的大公司都将云作为解决方案。
 
最重要的是,到2020年底,
  全球公共云服务收入
  预计将从2278亿美元增长到2664亿美元。边缘计算预计将随着云计算功能的升级而增长。实际上,预计
  全球Edge计算市场
  将从2018年的14.7亿美元增长到2025年的268.4亿美元。
 


 


 

5、预计会有新突破的语言:Rust,TypeScript,Kotlin和Swift


 
在过去的十年中,已经创建了数百种编程语言。这种从过去的单一语言的转变使开发人员能够使用专门的语言来工作,这些语言更加侧重于开发人员的人机工程学和硬件的现代化开发。
 
种类繁多的编程语言可使开发人员
  增强能力
 
  增强行业实力
  ,并将我们的重点转向解决人类问题。
  StackOverflow研究
  表明,到2020年,排名前四的现代编程语言将为Rust,TypeScript,Kotilin和Swift,其中Rust在过去四年中连续第四位。
 


 


 

6、 Kubernetes成为Mesos和Docker Swarm的胜利者


 
随着云计算的兴起,容器化应用程序的兴起。在这里,Kubernetes显然是赢家。随着云技术继续与我们的世界融合,Kubernetes将成为各地开发人员的重要工具。研究表明,Kubernetes的受欢迎程度持续上升。
  开发人员预测
  ,到2020年,我们将看到此流行应用程序的最佳实践和标准化的兴起。
 

 

 

 


 

7、Web框架:React继续发光


 
React对Web开发产生了巨大的影响,它带来的创新对开发人员都非常有用。它已被证明是过去一年中最主要的JavaScript框架。而统计数据表明,这种情况将持续数年。尽管其他框架(例如Vue)提供了自己独特的功能,但是
  React
  由于其灵活性和健壮性而受到许多人的
  青睐
 
 
而且,由于React得到了Facebook的支持,因此它将作为Web开发的标准在业界不断上升。查看这些Google趋势,以了解自2017年以来React在全球范围内的关注程度。
 

 



 

8、降低软件开发入门的门槛:会有越来越多的自学成才的程序员

尽管对技术行业有普遍的认识,但是软件开发的供需之间还是存在差距。随着全球大学价格的上涨,越来越少的人选择计算机科学专业。预计在未来几年内,软件开发人员的进入门槛将降低,从而为自学成才的开发人员腾出空间。
 
此外,一些开发人员预测,LCCS开发(低代码,无代码开发)将为企业创新提供增长,而无需CS学位持有者。
 
在线学习平台是行业转移的原因之一。Educative为所有级别的开发人员提供大学水平的课程,以提高他们的编码技能,并以低廉,无压力的成本处理新语言。2020年的目标是使世界各地的人们能够在没有大学负担的情况下加入发展世界,学习编程的队伍中来。
 


2020年Java语言发展现状

技术交流王叫兽 发表了文章 • 0 个评论 • 113 次浏览 • 2020-10-13 10:31 • 来自相关话题

作者 | Valeriia Karpenko译者 | 刘雅梦策划 | 陈思今年,Java 到达了一个不可思议的里程碑,达到了 25 岁的高龄。我们通过举办一个特别的在线 Java 日活动来庆祝它的诞生,在该活动中,许多专家演讲者分... ...查看全部
作者 | Valeriia Karpenko


译者 | 刘雅梦
策划 | 陈思

今年,Java 到达了一个不可思议的里程碑,达到了 25 岁的高龄。我们通过举办一个特别的在线 Java 日活动来庆祝它的诞生,在该活动中,许多专家演讲者分享了他们的经验,并就如何从这门语言中获得更多收益提供了技巧和窍门。

这引起了我们的思考,我们决定对数据进行深入研究,以彻底发现 Java 的普遍状态是什么,并帮助你回答一些亟待解决的问题。我们发现的某些内容可能是不足为奇的,但也有些见解是令人非常意想不到的。

随着 Java 15 在本周的发布,我们决定把它放在一起,向你展示 Java 的状态。这篇文章是根据不同来源的数据而创建的,其中包括我们的开发人员倡导者 Trisha Gee 的专家评论。

Java 开发者有多少,他们分布在哪里?

第一个问题是:“大多数的 Java 开发人员都在哪里,我们中有多少人是 Java 开发人员呢?”我们通过综合所能获取到的最准确的信息来回答这个问题,然后进行推断,得出一个我们认为非常合理的猜测。

市场研究和分析团队根据开发人员估算模型得出的最佳估计显示,当今世界上有大约 520 万专业 Java 开发人员,他们将 Java 作为主要语言。但是,如果我们将主要使用其他编程语言但同时也做一些 Java 工作的专业开发人员也包含在内的话,这个数字可能 接近 680 万。

至于这些 Java 开发人员都集中在什么地方,在亚洲居住的 Java 开发人员数量最多,那里大约有 250 万开发人员使用 Java 作为主要语言。北美和欧洲的数字远不及亚洲。你可能会问:“为什么呢?”好吧,起初我们有也有同样的想法,因此我们对这些区域进行了更深入的研究,以确切地了解这些数字的来源。


1.png哪个国家的 Java 开发者最多?

我们进一步研究了拥有最多 Java 开发人员的各个国家,然后调查了为什么这些国家在专业开发中特别喜欢 Java 而不是其他语言。

下图显示了每个国家使用 Java 作为主要语言的开发人员的百分比(用于收集此数据的调查对象最多可以选择 3 种主要语言)。中国韩国 的数值最高,分别约为 51%和 50%。数据来自 2020 年开发者生态系统状况调查

专家分析

Java 在前 6 个国家如此流行的原因可能包括 Java 是免费使用的、政府支持和开源。对于 中国、西班牙巴西 尤其是这样。它是在 中国和印度 进行 Android 移动开发的基础,并且雇佣海外人员用 Java 开发手机应用程序非常普遍,这可能是 印度 使用量达到峰值的原因。德国 的使用率也很高,这可以归因于 Java 在 德国 软件工程师中是最流行的语言,因为多种行业都使用 Java 来构建高度可扩展的应用程序。大多数企业服务都依靠 Java 来驱动应用程序支持日常业务的运行,例如工资单、库存管理、报表等。德国还有一个庞大的金融部门,在本国技术上大量使用 Java,例如交易机器人、零售银行系统以及金融业为了保持竞争所需要的其他应用程序。

我们本以为美国会有很高比例的 Java 用户,但是并没有,这也是很合理的。有大量的技术栈可供选择,而且很多技术公司通常处于这些技术栈的最前沿,因此那里的开发人员可能不需要 Java 的强大功能或稳定性,而是使用能让他们进行快速构建和测试等的语言。

2.pngJava 在开发行业中的位置

根据 2020 年开发者生态系统状况调查,有超过三分之一的专业开发人员将 Java 用作主要语言,而 Java 在专业开发人员当中仍然是仅次于 JavaScript 的第二大主要语言。

专家分析

看到 JavaScript 和 Java 处于领先地位,这并不奇怪,因为它们是成对的:使用 Java 的开发人员经常使用 JavaScript 编写前端和任意快速脚本。由于机器学习的普及,Python 可能排名第三。一般来说,我们希望 Web 成为开发人员生态系统的重要组成部分,因此 JavaScript、HTML 和 CSS 以及 PHP 将始终能拥有稳固的地位。SQL 也会一直存在,因为没有多少东西是不需要某种容量的数据库的。C++ 也是一种坚实的语言,因为它被用于许多嵌入式应用程序中,因此它不会很快在图表中消失。虽然 C# 似乎正在逐渐衰落,但我想如果 Java 比例高,C# 就会低,因为它们在功能上非常相似。至于为什么我认为 Java 在专业发展领域如此之高,原因与之前提到的德国类似。大多数企业的业务服务都依靠 Java 来运行。它不仅仅用于 IT 部门,几乎每个公司,无论是分销、制造还是银行业,都将 IT 服务作为其基础设施的一部分,而这些服务,如工资单或库存管理,通常都是在后端使用 Java 构建的。因此,Java 被这些公司的专业开发人员所大量使用。

3.png用 Java 开发的软件类型

快速浏览一下用 Java 开发的软件类型,应该可以了解它的使用统计信息。根据2020 年开发者生态系统状况调查的结果,Java 使用最流行的领域是 Web 服务,占 52%。

专家分析

看到 Java 在商业智能 / 数据科学 / 机器学习中如此流行,真令人惊讶,因为你可能认为这将是 Python 的领域。其他的就不足为奇了,因为 Web 服务的后端通常是 Java,而且使用 Java 编写业务应用程序也很有意义,因为它们也需要使用后端和数据库。

4.png使用 Java 的热门行业

既然我们知道了为什么这么多专业开发人员使用 Java,那么让我们具体看看 Java 应用于哪些行业。

根据 2020 年开发者生态系统状况调查,Java 程序 主要用于 IT 服务(42%)与金融和金融科技领域(44%),但这并不是说 Java 没有用于其他行业。

专家分析

金融和金融科技领域主要涉及金融交易所、零售银行系统、创建计算引擎以及开发本地定制工具和服务,以使公司在市场上具有竞争力。金融和金融科技几乎都是用 Java 建立的,所以在这里没有什么好惊讶的。IT 服务也是如此,因为许多针对非 IT 公司的薪资系统和库存管理服务都是基于 Java 构建的。其他行业也很有趣。由于 Android 的存在,移动开发的比例可能很高,因此 Java 正以这种方式被使用。大数据和数据分析也非常有趣,因为该行业是由 Python 主导的,但是后端可能会使用 Java 和 JVM 语言。当然构建软件开发工具也可以。JetBrains IDE 目前是用 Java 构建的。尽管其他行业有点神秘,但实际上,了解 Java 在这些行业中的使用方式将非常有趣。

5.pngJava 相关工具

Java 版本

Java 8 仍然是最受欢迎的版本。在使用 Java 作为主要语言的专业开发人员当中,有 75%的人使用 Java 8。基于开发人员在 2020 年开发者生态系统状况调查 中选择的几个版本,下图显示了 Java 版本的分布情况。

专家分析

有几个因素导致了 Java 8 的如此流行。首先,它拥有典型的 Java 开发人员所需要的所有语言,它具有 lambda 和流,并且它是一个很好的易于使用的版本。另外,人们一直不愿意迁移到 Java9。Java9 引入了一些重大的架构更改,人们担心这些更改会破坏他们用 Java 8 构建的应用程序。最重要的是,Oracle 还推出了每两年发布一次的版本,因此并不是所有版本都是长期受支持的,因此 Java 9、Java 10、Java 12 和 Java 13 仅受 6 个月的支持,这可能就是为什么它们都只有这么少用户的原因。Java 13 之所以如此之高,是因为当本调查公布时,它是最新的版本,因此你可以预期,该数字将在几个月后下降。

Java 11 发布于 2018 年,它是长期受支持的最新版本。许多企业仍未迁移到它,因为他们担心超过 Java 9(由于其架构的更改)会破坏一切,而且 Java 11 引入了新的许可和新的订阅,因此它带来了一个新的恐惧:更担心如果使用了错误的版本,以错误的方式使用它,Oracle 会对你进行罚款。许多开发人员没有升级到 Java 11 的最后一个主要因素是,它没有很多令人兴奋的新功能,因此该语言的功能并没有降低升级的风险。Java 17 将是下一个拥有长期支持的版本,并带有许多新功能,但是直接从 Java 8 升级到 Java 17 也会带来一些问题。

我的预测是,我认为下一个长期版本 Java 17 将比上一个 LTS(长期支持版本)Java 11 更受欢迎。不过,作为 Java 17 的准备,这一点我再强调也不为过,建议你先将代码库更新到 Java 11,然后再更新为 Java 17,以避免出现大问题。

6.png流行的应用服务器

在过去的 3 年中,Apache Tomcat 仍然是最受欢迎的应用服务器,而 JBoss EAP 和 WildFly 的使用量却减少了一半。给出的数据来自参加 2018 年 和 2020 年 开发者生态系统调查的所有以 Java 为主要语言的开发人员。

专家分析

Jetty 位居第二,但它确实低得令人惊讶。可能是某些正在使用 Spring Boot 和其他微服务框架的开发人员没有意识到他们到底在使用使用,他们可能在不知不觉中使用了 Tomcat 或 Jetty。

7.png排名前 5 的 Web 框架

在 2018 年,Spring Boot 与 Spring MVC 是一样流行的,到了 2020 年,它变得更加流行。给出的数据来自所有使用 Java 作为主要语言的开发人员。

专家分析

这基本上只是在证实 Spring 拥有市场。几乎可以肯定的是,仍然有人在使用 Struts 1,但它只是用于遗留应用程序。

8.png排名前 5 的分析器

2020 年开发者生态系统状况调查 显示,有 24%的用户使用 VisualVM,而一半的用户则没有使用。给出的数据来自所有使用 Java 作为主要语言的开发人员。

9.png

排名前 5 的 IDE/ 编辑器

2018 年 和 2020 年 的开发者生态系统调查显示,IntelliJ IDEA 的份额从 2018 年的 55%增加到 2020 年的 72%,而其他四个的使用率则有所下降。

专家分析

不过,即使我们对调查结果进行了加权,但我们并不否认这些信息可能会有些偏差,因为这是来自 JetBrains 开发者生态系统状态调查,而 JetBrains 的一个主要产品就是 IntelliJ IDEA。然而,这并不是说这并非完全不合理,就好像我们在其他调查中看到的一样,IntelliJ IDEA 通常是使用最多的 IDE 之一,并且通常拥有约 55-60%的用户份额。VS Code 正在增长,这不是从竞争的角度来看的,而是从缺乏对 IDE 的理解的角度来看的。VS Code 是一个代码编辑器,带有一些你可以在 IDE 中找到的特性,并且可以提供附加功能的扩展。因此,如果人们使用 VS Code 进行开发,则可能意味着开发人员不知道一个功能齐全的 IDE 能给他们什么。在 Web 领域,使用编辑器是可以理解的,因为 Web 开发人员通常使用动态语言,并且经常使用其他工具(例如浏览器插件)来满足他们的需求。但是在 Java 中,特别是在专业的 Java 中,你确实可以从一个与应用程序服务器集成的优秀工具中得到很多东西,你可以真正使用分析、重构等功能。

我们专家的最新消息

我发现有很多对本博客文章数据分析进行删减和编辑的版本,这是我无意间造成的混乱。我想澄清一下我对开发人员和 IDE 评论背后的意图。对我来说,如果开发人员不理解 IntelliJ IDEA 作为一个功能齐全的 IDE 给他们带来了什么,那对我来说就是一个失败,因为这六年来我的工作就是让开发人员了解 IDE(特别是 IntelliJ IDEA)能为你做什么。我强烈地认为,人们不应该因为不了解产品而责备用户或潜在用户。

我个人对 IDE 的观点来自拥有 20 多年 Java 开发经验的 Java 开发人员,他们开发过各种大大小小的 Java 项目。如果没有像 IntelliJ IDEA 这样的 IDE 提供大量的帮助,我无法想象如何创建一个复杂的企业应用程序。我也见过很多开发人员使用 VS Code,并且我完全了解代码编辑器所涵盖的用例。在你的工具箱中总有能容纳多于一种的工具,了解某个工具的优点将有助于我们为正确的工作选择合适的工具。

10.png讨论最多的 Java 工具和其他语言

在 IT 社区中会经常讨论 Java,其中的一个社区就是 Stack Overflow。我们从 “问答”部分 中获取了数据,以找出哪些标签与“ java”最相关。纵轴表示提到 Java 的次数,横轴表示标签出现的总次数。

专家分析

对于那些希望确保自己使用了正确的技术或正寻找适合自己的工具的用户来说,这个图表可能很有用。这些语言很有意思,但这可能是因为人们正在寻找 Java 与其他语言之间的比较。正则表达式是人们苦苦挣扎的一个利基领域,但它能上榜也就不足为奇了。

11.pngJava 社区的热门话题

Java 的讨论

我们分析了 Reddit 上“ java”子版块的帖子,并发现了 Java 用户在 Reddit 上讨论最多的主题。

专家分析

这些正是我期望看到的话题。例如,用 Java 编写代码的人总是会对这种语言是否仍然有需求感兴趣,毕竟,这种语言还在发展。我们刚刚庆祝了 Java 诞生 25 周年,因此人们希望检查它是否过时了,以及它是否仍然有效。特别是,如果他们刚从大学毕业,还不知道他们所学的语言是否能为他们提供工作机会。在容器中部署 Java 是一个非常热门的话题,包括我在内,这是每个人都想知道的东西,但几乎找不到任何相关信息。我对性能优化这个主题并不感到惊讶,尽管我认为这个主题有点多余,因为大多数应用程序实际上并不需要开发人员来进行优化,尽管许多开发人员认为这是一项重要的职业技能。使后端和前端协同工作也非常复杂,我可以想到有很多关于这方面的问题。

12.png

原文链接:

https://blog.jetbrains.com/idea/2020/09/a-picture-of-java-in-2020/



跳来跳去,程序员到底去大公司还是小公司?

技术交流大兴 发表了文章 • 0 个评论 • 93 次浏览 • 2020-10-10 18:30 • 来自相关话题

职场生涯总会面临着选择,尤其对我们这些 IT 人来说,跳槽的频率应该是所有行业中相当大的了。那么我们跳来跳去,究竟该选择什么样的公司 ?大 or 小 。工作三年多了,经历一大一小,最近也面试了不少家公司,形态各异,说说自己的感受想法。在小公司中,给我个人的印象... ...查看全部

untitled.png

职场生涯总会面临着选择,尤其对我们这些 IT 人来说,跳槽的频率应该是所有行业中相当大的了。那么我们跳来跳去,究竟该选择什么样的公司 ?大 or 小 。

工作三年多了,经历一大一小,最近也面试了不少家公司,形态各异,说说自己的感受想法。

在小公司中,给我个人的印象大多数环境都不怎么样。定义下这个小公司规模吧,在几人到几十人吧,反正不会超过100人。

亲历一家小公司, 面试见过数家小型公司。我觉得大概分两种:

1.真正的黑穷丑

入职原因:实在没地方去了,毕业什么也不会,来做苦工吧

缺点:加班是家常便饭、工资少的可怜、福利基本没有,事事都要你干

优点:锻炼你顽强的意志力、培养男人的愤怒血性,当然干的多了能力自然也会有提升,不过如果没有牛人带且自己也不是特强的话,你的视野应该是比较窄的

2.有稳定业务、公司盈利还不错,待遇也可以媲美大公司

缺点:还是个人视野的问题,如果你个人能力很好,不是野心很大,在小公司也不错

优点:至少福利待遇不会差,环境也还可以,公司小自己做的贡献领导会看到,做个2,3年可能就是公司的主干力量了,有成就感。

说说自己的第一家公司,那个小公司

自己毕业时选择的是这家小公司,说选择当时是有对比,而最终决定去这家小公司的原因是他给开了3k的工资,比其他两个相对大的公司多,于是就去了,虽然环境不怎么样,自己也忍了,觉得应该锻炼机会很多吧,有家公司环境着实不错,可是帝都1600的工资实在觉得跌面儿。

正像我说的第2种小公司一样,老板有自己的关系公司每年的盈利还不错,几十人的小公司过的也还算舒服。工资每年都会涨,没用自己提过,基本在一年1k左右,毕业刚去的那年发了5k的年终奖,欣喜的不亦乐乎。

在公司的工作就是做一些小项目,很少加班,开始有人带,而后就是自己做项目,整个项目的方方面面,再后来还要带一些刚毕业的小弟弟,实在不敢以师傅挂名,羞愧不敢当,觉得自己的水平不够,于是考虑到在该公司的状况也就如此了,自己又不是视野很宽知道学什么的主,于是有了离开的打算,想去看看国外的月亮。

没见过国外的月亮,都会觉得外面的月亮是更圆的。尽管工作2年的时候工资翻了一倍,那年的年终奖也拿到2w多的地步,老板器重的情况下,还是选择了了离开。

觉得外面的世界很精彩,自己需要出去看看,就这样离开了,来到了一家规模还比较大的互联网公司,虽然工资只比原来多了1k,还是去了,觉得神秘的大公司应该可以学习到不少的东西吧。

很庆幸,刚毕业没有遇见第一种小公司,一些脏乱差,到处摆满东西的公司在后来的面试时还真是见过几个。

一个插曲:一个什么外包公司要我去面试,进去后一看里面安了很多挡板,临时搭的那种,我以为公司发展过来的小分部,随后了解说这是公司总部,汗颜。

来到了大公司

虽然钱没多挣(也许还不如以前的多),但一下子觉得自己牛逼了不少,因为自己的公司耳熟能详啊,可以和别人吹牛逼,也可以给自己的职业生涯贴贴金。

干净的办公环境,每过一会儿就有人清理的卫生间,正版的操作系统、应用软件,公司项目用的新技术,一切的一切都是新鲜的,就像一个村儿逼来到了城里看见了摩天大厦,豁然开朗。周围人也都是4,5年工作经验的牛人……

也就是半年吧,新鲜感过了,也没什么了。唯一感觉的就是觉得工作无聊,整天维护着那么一个小项目,有时很长时间都不知道做什么,也许是自己的问题吧,但是我确定的是这不是我想要的,跟我想的不一样。

不过在该公司的一年多时间里,技术上有一定的提高、见识也增长了不少,但是更大的变化是自己的思想发生了很大的改变。

以前觉得自己是一个.net程序员,就像园子里曾经有人说,这个叫法很蹩脚很奇怪,确实是这样,我们为什么要把自己定义为一个xx程序员?而我们只是一个程序员啊,写代码的程序员,不管是java、c#、php、python、javascript…. 这是一个重要改变。

一直在想,我追求的所谓大公司,到底追求的是什么?

离开第一家小公司想要追求的东西,想要有人带,有高手指导,而这只不过是自己能力的欠缺与知识获取方面能力的不足罢了。

当我们自己这两方面足够强大的时候,我们就成为了高手,不再需要别人的指导,你追求的大公司也就成为了一个空壳。

所以我觉得,大公司、小公司都无所谓,首先我们要让自己牛逼,或者知道怎样牛逼起来,然后再有施展技能的平台就够了,大、小只是一个壳罢了,问题的根源在于你是否能够牛逼起来!