来到掘金的第一篇文章,话不多说开始进入正题;openai携带者chatgpt席卷全球之际,我们却被拒之门外,以往的科学上网也只是前提条件,国内的邮箱也无法使用,下面是目前使用 chatgpt的准备条件:
- 科学上网
- 注册一个Google账号
- 准备一个国外的手机号(虚拟号码不能是漂亮国的,他们有校验),因为用谷歌账号登录完还需要短信验证码进行验证,虚拟手机号获取可以使用接码平台。
关于chatgpt的注册教程网上有很多,大家可以搜索一下,这里主要介绍一下chatgpt对程序员的帮助。这里以flutter举例,比如我现在有一个需求:
做一个聊天的页面,内容包括
- 封装一个气泡widegt
- 消息内容要求一个字一个字的显示
- 消息内容支持换行
- 底部有一个输入框,支持用户输入、发送消息
- 输入框最多显示3行,超出部分支持滚动
我们看看chatgpt帮我们写的代码
1. bubble.dart
import 'package:flutter/material.dart';
import 'chat_page.dart';
class AnimatedText extends StatefulWidget {
final String message;
final bool isMe;
final bool shouldAnimate;
final bool isLast;
const AnimatedText({required this.message, required this.isMe, required this.shouldAnimate, this.isLast = false});
@override
_AnimatedTextState createState() => _AnimatedTextState();
}
class _AnimatedTextState extends State<AnimatedText> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<int> _animation;
@override
void initState() {
super.initState();
if (widget.shouldAnimate) {
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 5000));
_animation = IntTween(begin: 0, end: widget.message.length).animate(_controller)
..addListener(() {
setState(() {});
});
_controller.forward();
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final text = widget.shouldAnimate? widget.message.substring(0, _animation.value) : widget.message;
if (widget.isLast) {
ChatScreenState? chatState = context.findAncestorStateOfType<ChatScreenState>();
chatState?.scrollToBottom();
}
return Wrap(
alignment: widget.isMe ? WrapAlignment.end : WrapAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: widget.isMe ? Colors.blueAccent : Colors.grey[300],
borderRadius: BorderRadius.circular(20.0),
),
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
child: Text(
text,
style: TextStyle(
color: widget.isMe ? Colors.white : Colors.black,
fontSize: 16.0,
),
),
),
],
);
}
}
2. chatScreen.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'bubble.dart';
class ChatScreen extends StatefulWidget {
@override
State<ChatScreen> createState() => ChatScreenState();
}
class ChatScreenState extends State<ChatScreen> {
final List<Map<String, dynamic>> messages = [
{"text":'Hello, how are you?', "isMe":true},
{"text":'I'm doing well,thanks. How about you?', "isMe":false},
{"text":"去你的,还不错,不错个毛。喵的找你聊天都找不到,跟小签学会了是吧", "isMe": true},
{"text":"对不起,我错了,以后再也不敢了", "isMe": false},
];
final TextEditingController _controller = TextEditingController();
final ScrollController _scrollController = ScrollController();
var _isInputed = false;
void _sendMessage(String message) {
_isInputed = true;
setState(() {
messages.add({"text":message, "isMe":true});
});
Future.delayed(Duration(seconds: 2)).then((value) {
messages.add({"text":"自动回复消息:你好!请稍后再聊", "isMe":false});
setState(() {
});
});
_controller.clear();
}
//滚动到底部
scrollToBottom() {
// Future.delayed(Duration(seconds: 1)).then((value) {
_scrollController.animateTo(_scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 300), curve: Curves.easeOut);
// });
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat Screen')),
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(child: getListView()),
getInputView(),
SizedBox(
height: 20,
)
],
),
),
);
}
Widget getListView() {
return ListView.builder(
controller: _scrollController,
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
bool isLast = index == messages.length-1;
return AnimatedText(
message: messages[index]["text"],
isMe:messages[index]["isMe"],
shouldAnimate:_isInputed && isLast && !messages[index]["isMe"],
isLast: _isInputed && isLast,
);
},
);
}
Widget getInputView() {
return Row(
children: [
SizedBox(width: 8,),
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(4),
hintText: '请输入消息...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16.0),
),
),
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 3,
// expands: false,
maxLengthEnforcement: MaxLengthEnforcement.enforced,
),
),
IconButton(
icon: Icon(Icons.send),
onPressed: () => _sendMessage(_controller.text),
),
// SizedBox(width: 16,),
],
);
}
}
3. 我们把chartScreen 在main.dart里面调用一下
import 'package:flutter/material.dart';
import 'chat_page.dart';
void main() => runApp(const App());
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChatScreen()
);
}
}
4. 运行看看效果
总结
1. 感叹ai的强大
以前碰到im大家可能会觉得恐惧,又要写气泡,适配,支持换行,计算高度等,现在交给ai就可以了,他可以帮我们把整体功能实现,我们只需要在这个基础上少做调整,当然以上代码并非100%由chatgpt生成的,其中有一丢丢是我在它提供的代码基础上稍作调整的,比如自动回复、初始化的聊天内容是我后加的。当然了有兴趣也可以试一下,让chatgpt帮我们做一个登录界面,因为这个需求比较好描述,ai理解起来比较明确,所以生成的代码是可以直接用的。后续扩展需的功能也比较简单,比如对邮箱加正则校验、密码长度大小写混合校验等,都是直接可以直接生成的
2. 插件
现在也有很多好用的插件可以集成进IDE,不过大多是要收费的,对于Android studio这样比较笨重IDE,我试了几个不过效果都不太好;对于使用vscode的推荐一个免费的插件codeium,这个对于python的支持尤其强大,开发的过程中,可以把需求档注释写,写完注释代码自动生成。
3.openai提示1020的错误
今天发现openai不能访问了,提示1020的错误,对于这个问题我是很迷惑的,因为我一直是通过日本的IP访问的,不知道怎么就无法访问了。好在尝试几次可以继续访问了,我主要是先把coockie清掉,然后换到新加坡的IP就可以了