千问3.5-9B Android Studio移动端AI应用开发入门

1. 移动端AI应用开发新选择

最近在开发移动端AI应用时,发现千问3.5-9B模型是个不错的选择。这个模型体积适中,响应速度快,特别适合在移动端通过API调用。今天我就来分享下,如何在Android Studio中快速开发一个集成千问3.5-9B的聊天应用。

相比直接在服务器部署大模型,这种前后端分离的方式有几个明显优势:一是手机不需要承担模型推理的算力负担;二是可以随时切换不同模型服务;三是应用包体不会因为内置模型而变得臃肿。

2. 开发环境准备

2.1 Android Studio下载与安装

首先需要准备好开发环境。如果你还没安装Android Studio,可以到官网下载最新版本。安装过程很简单,基本上就是一路"下一步"。不过有几点需要注意:

  • 确保电脑满足最低配置要求(至少8GB内存,推荐16GB)
  • 安装时勾选Android SDK和必要的工具链
  • 安装完成后,记得通过SDK Manager安装对应版本的Android SDK

2.2 创建新项目

打开Android Studio后,选择"Start a new Android Studio project"。在模板选择界面,推荐使用"Empty Activity",这样可以从零开始构建我们的AI聊天应用。

项目配置时要注意:

  • 语言选择Kotlin(当然你也可以用Java,但Kotlin现在是官方推荐语言)
  • 最低API级别建议设为24(Android 7.0),这样可以覆盖大多数设备
  • 其他设置保持默认即可

3. 基础界面搭建

3.1 设计聊天界面

我们的AI聊天应用需要几个基本组件:

  • 一个显示对话历史的RecyclerView
  • 底部的输入框和发送按钮
  • 简单的消息气泡样式

在res/layout/activity_main.xml中,可以这样布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/chatRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        <EditText
            android:id="@+id/messageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="输入你的问题..."/>
            
        <Button
            android:id="@+id/sendButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送"/>
    </LinearLayout>
</LinearLayout>

3.2 实现消息适配器

为了在RecyclerView中显示聊天消息,我们需要创建一个消息适配器:

class MessageAdapter(private val messages: MutableList<Message>) : 
    RecyclerView.Adapter<MessageAdapter.MessageViewHolder>() {

    inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val messageText: TextView = itemView.findViewById(R.id.messageText)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
        val layout = if (viewType == MSG_TYPE_SENT) {
            R.layout.item_message_sent
        } else {
            R.layout.item_message_received
        }
        val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
        return MessageViewHolder(view)
    }

    override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
        holder.messageText.text = messages[position].content
    }

    override fun getItemCount() = messages.size

    override fun getItemViewType(position: Int) = messages[position].type
}

4. 集成千问3.5-9B API

4.1 添加网络请求依赖

在app/build.gradle文件中添加Retrofit和Gson依赖:

dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
}

4.2 创建API服务接口

定义与千问3.5-9B后端服务通信的接口:

interface QwenAIService {
    @POST("/v1/chat/completions")
    suspend fun chatCompletion(
        @Body request: ChatRequest
    ): Response<ChatResponse>
}

data class ChatRequest(
    val model: String = "qwen-3.5-9B",
    val messages: List<Message>,
    val temperature: Float = 0.7f
)

data class ChatResponse(
    val choices: List<Choice>
)

data class Choice(
    val message: Message
)

data class Message(
    val role: String,
    val content: String
)

4.3 实现网络请求

创建一个Retrofit实例并实现API调用:

object QwenAIClient {
    private const val BASE_URL = "https://your-qwen-api-server.com"
    
    private val retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(
                OkHttpClient.Builder()
                    .addInterceptor(HttpLoggingInterceptor().apply {
                        level = HttpLoggingInterceptor.Level.BODY
                    })
                    .build()
            )
            .build()
    }
    
    val service: QwenAIService by lazy {
        retrofit.create(QwenAIService::class.java)
    }
}

5. 实现完整聊天流程

5.1 发送消息处理

在MainActivity中实现发送消息的逻辑:

class MainActivity : AppCompatActivity() {
    private lateinit var adapter: MessageAdapter
    private val messages = mutableListOf<Message>()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        adapter = MessageAdapter(messages)
        chatRecyclerView.adapter = adapter
        chatRecyclerView.layoutManager = LinearLayoutManager(this)
        
        sendButton.setOnClickListener {
            val userMessage = messageEditText.text.toString()
            if (userMessage.isNotBlank()) {
                // 添加用户消息到列表
                addMessage(Message(role = "user", content = userMessage))
                messageEditText.text.clear()
                
                // 发送到AI并获取回复
                CoroutineScope(Dispatchers.IO).launch {
                    try {
                        val response = QwenAIClient.service.chatCompletion(
                            ChatRequest(messages = messages)
                        )
                        
                        if (response.isSuccessful) {
                            val aiMessage = response.body()?.choices?.first()?.message
                            aiMessage?.let {
                                withContext(Dispatchers.Main) {
                                    addMessage(it)
                                }
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
        }
    }
    
    private fun addMessage(message: Message) {
        messages.add(message)
        adapter.notifyItemInserted(messages.size - 1)
        chatRecyclerView.smoothScrollToPosition(messages.size - 1)
    }
}

5.2 实现消息缓存

为了提升用户体验,我们可以添加简单的消息缓存功能:

object ChatCache {
    private const val PREFS_NAME = "ChatPrefs"
    private const val KEY_MESSAGES = "messages"
    
    fun saveMessages(context: Context, messages: List<Message>) {
        val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        val json = Gson().toJson(messages)
        prefs.edit().putString(KEY_MESSAGES, json).apply()
    }
    
    fun loadMessages(context: Context): List<Message> {
        val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        val json = prefs.getString(KEY_MESSAGES, null)
        return if (json != null) {
            val type = object : TypeToken<List<Message>>() {}.type
            Gson().fromJson(json, type) ?: emptyList()
        } else {
            emptyList()
        }
    }
}

然后在Activity中适当位置调用保存和加载方法:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...其他代码...
    
    // 加载历史消息
    messages.addAll(ChatCache.loadMessages(this))
    adapter.notifyDataSetChanged()
}

override fun onPause() {
    super.onPause()
    // 保存当前对话
    ChatCache.saveMessages(this, messages)
}

6. 优化与改进建议

现在我们已经完成了一个基本的千问3.5-9B移动端集成应用,但还有几个可以优化的地方:

首先是网络状态处理。实际应用中应该检查网络连接,并在离线时给出提示。可以添加一个网络状态监听器:

private fun checkNetworkConnection(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork = connectivityManager.activeNetwork
    val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
    return networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true
}

其次是加载状态提示。在等待AI回复时,可以显示一个加载动画,提升用户体验。最简单的方式是添加一个ProgressBar到布局中,并在请求开始和结束时控制其可见性。

最后是错误处理。网络请求可能会失败,应该给用户适当的反馈。可以在catch块中添加Toast提示:

catch (e: Exception) {
    withContext(Dispatchers.Main) {
        Toast.makeText(this@MainActivity, "请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
    }
}

获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐