本文目录导读:

- 项目结构
- 实体类(Task.java)
- 数据库助手(DatabaseHelper.java)
- 适配器(TaskAdapter.java)
- 主活动(MainActivity.java)
- 布局文件
- build.gradle 依赖
- 功能特点
- 运行效果
我来为您提供一个完整的Java移动开发案例 —— 一个简易的待办事项应用(Todo App)。
项目结构
TodoApp/
├── app/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/com/example/todoapp/
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── TaskAdapter.java
│ │ │ │ ├── Task.java
│ │ │ │ └── DatabaseHelper.java
│ │ │ └── res/
│ │ │ ├── layout/
│ │ │ │ ├── activity_main.xml
│ │ │ │ └── item_task.xml
│ │ │ └── values/
│ └── build.gradle
实体类(Task.java)
package com.example.todoapp;
public class Task {
private int id;
private String title;
private String description;
private boolean completed;
private String createDate;
public Task() {
}
public Task(String title, String description, boolean completed, String createDate) {
this.title = title;
this.description = description;
this.completed = completed;
this.createDate = createDate;
}
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
}
数据库助手(DatabaseHelper.java)
package com.example.todoapp;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "todo.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_TASKS = "tasks";
private static final String COLUMN_ID = "id";
private static final String COLUMN_TITLE = "title";
private static final String COLUMN_DESCRIPTION = "description";
private static final String COLUMN_COMPLETED = "completed";
private static final String COLUMN_CREATE_DATE = "create_date";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + TABLE_TASKS + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_TITLE + " TEXT NOT NULL, " +
COLUMN_DESCRIPTION + " TEXT, " +
COLUMN_COMPLETED + " INTEGER DEFAULT 0, " +
COLUMN_CREATE_DATE + " TEXT)";
db.execSQL(createTable);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_TASKS);
onCreate(db);
}
// 添加任务
public long addTask(Task task) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE, task.getTitle());
values.put(COLUMN_DESCRIPTION, task.getDescription());
values.put(COLUMN_COMPLETED, task.isCompleted() ? 1 : 0);
values.put(COLUMN_CREATE_DATE, task.getCreateDate());
long id = db.insert(TABLE_TASKS, null, values);
db.close();
return id;
}
// 获取所有任务
public List<Task> getAllTasks() {
List<Task> taskList = new ArrayList<>();
String selectQuery = "SELECT * FROM " + TABLE_TASKS + " ORDER BY " + COLUMN_CREATE_DATE + " DESC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
Task task = new Task();
task.setId(cursor.getInt(cursor.getColumnIndex(COLUMN_ID)));
task.setTitle(cursor.getString(cursor.getColumnIndex(COLUMN_TITLE)));
task.setDescription(cursor.getString(cursor.getColumnIndex(COLUMN_DESCRIPTION)));
task.setCompleted(cursor.getInt(cursor.getColumnIndex(COLUMN_COMPLETED)) == 1);
task.setCreateDate(cursor.getString(cursor.getColumnIndex(COLUMN_CREATE_DATE)));
taskList.add(task);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return taskList;
}
// 更新任务
public int updateTask(Task task) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE, task.getTitle());
values.put(COLUMN_DESCRIPTION, task.getDescription());
values.put(COLUMN_COMPLETED, task.isCompleted() ? 1 : 0);
return db.update(TABLE_TASKS, values, COLUMN_ID + " = ?",
new String[]{String.valueOf(task.getId())});
}
// 删除任务
public void deleteTask(int id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_TASKS, COLUMN_ID + " = ?",
new String[]{String.valueOf(id)});
db.close();
}
}
适配器(TaskAdapter.java)
package com.example.todoapp;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {
private List<Task> taskList;
private Context context;
private OnTaskListener onTaskListener;
public interface OnTaskListener {
void onTaskClick(Task task);
void onTaskLongClick(Task task);
void onTaskCheckChange(Task task, boolean isChecked);
}
public TaskAdapter(List<Task> taskList, OnTaskListener listener) {
this.taskList = taskList;
this.onTaskListener = listener;
}
@NonNull
@Override
public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View view = LayoutInflater.from(context)
.inflate(R.layout.item_task, parent, false);
return new TaskViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull TaskViewHolder holder, int position) {
Task task = taskList.get(position);
holder.bind(task);
}
@Override
public int getItemCount() {
return taskList.size();
}
class TaskViewHolder extends RecyclerView.ViewHolder {
TextView titleText;
TextView descText;
TextView dateText;
CheckBox completedCheckBox;
TaskViewHolder(View itemView) {
super(itemView);
titleText = itemView.findViewById(R.id.textTitle);
descText = itemView.findViewById(R.id.textDescription);
dateText = itemView.findViewById(R.id.textDate);
completedCheckBox = itemView.findViewById(R.id.checkCompleted);
itemView.setOnClickListener(v -> {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && onTaskListener != null) {
onTaskListener.onTaskClick(taskList.get(position));
}
});
itemView.setOnLongClickListener(v -> {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && onTaskListener != null) {
onTaskListener.onTaskLongClick(taskList.get(position));
return true;
}
return false;
});
completedCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && onTaskListener != null) {
Task task = taskList.get(position);
task.setCompleted(isChecked);
onTaskListener.onTaskCheckChange(task, isChecked);
}
});
}
void bind(Task task) {
titleText.setText(task.getTitle());
descText.setText(task.getDescription());
completedCheckBox.setChecked(task.isCompleted());
// 格式化日期显示
try {
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
SimpleDateFormat outputFormat = new SimpleDateFormat("MM月dd日 HH:mm", Locale.getDefault());
Date date = inputFormat.parse(task.getCreateDate());
if (date != null) {
dateText.setText(outputFormat.format(date));
}
} catch (Exception e) {
dateText.setText(task.getCreateDate());
}
// 根据完成状态设置样式
if (task.isCompleted()) {
titleText.setAlpha(0.5f);
descText.setAlpha(0.5f);
} else {
titleText.setAlpha(1f);
descText.setAlpha(1f);
}
}
}
}
主活动(MainActivity.java)
package com.example.todoapp;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements TaskAdapter.OnTaskListener {
private RecyclerView recyclerView;
private TaskAdapter adapter;
private List<Task> taskList;
private DatabaseHelper databaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseHelper = new DatabaseHelper(this);
taskList = new ArrayList<>();
initViews();
loadTasks();
setupRecyclerView();
}
private void initViews() {
recyclerView = findViewById(R.id.recyclerView);
FloatingActionButton fab = findViewById(R.id.fabAdd);
fab.setOnClickListener(v -> showAddTaskDialog());
}
private void setupRecyclerView() {
adapter = new TaskAdapter(taskList, this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
private void loadTasks() {
taskList.clear();
taskList.addAll(databaseHelper.getAllTasks());
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
private void showAddTaskDialog() {
LayoutInflater inflater = LayoutInflater.from(this);
View dialogView = inflater.inflate(R.layout.dialog_add_task, null);
EditText etTitle = dialogView.findViewById(R.id.etTitle);
EditText etDescription = dialogView.findViewById(R.id.etDescription);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("添加新任务")
.setView(dialogView)
.setPositiveButton("添加", (dialog, which) -> {
String title = etTitle.getText().toString().trim();
String description = etDescription.getText().toString().trim();
if (title.isEmpty()) {
Toast.makeText(this, "请输入任务标题", Toast.LENGTH_SHORT).show();
return;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String createDate = sdf.format(new Date());
Task task = new Task(title, description, false, createDate);
long id = databaseHelper.addTask(task);
if (id > 0) {
loadTasks();
Toast.makeText(this, "任务添加成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "添加失败", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", null)
.show();
}
private void showEditTaskDialog(Task task) {
LayoutInflater inflater = LayoutInflater.from(this);
View dialogView = inflater.inflate(R.layout.dialog_add_task, null);
EditText etTitle = dialogView.findViewById(R.id.etTitle);
EditText etDescription = dialogView.findViewById(R.id.etDescription);
etTitle.setText(task.getTitle());
etDescription.setText(task.getDescription());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("编辑任务")
.setView(dialogView)
.setPositiveButton("保存", (dialog, which) -> {
String title = etTitle.getText().toString().trim();
String description = etDescription.getText().toString().trim();
if (title.isEmpty()) {
Toast.makeText(this, "请输入任务标题", Toast.LENGTH_SHORT).show();
return;
}
task.setTitle(title);
task.setDescription(description);
int result = databaseHelper.updateTask(task);
if (result > 0) {
loadTasks();
Toast.makeText(this, "任务更新成功", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", null)
.show();
}
private void showDeleteDialog(Task task) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("删除任务")
.setMessage("确定要删除这个任务吗?")
.setPositiveButton("删除", (dialog, which) -> {
databaseHelper.deleteTask(task.getId());
loadTasks();
Toast.makeText(this, "任务已删除", Toast.LENGTH_SHORT).show();
})
.setNegativeButton("取消", null)
.show();
}
@Override
public void onTaskClick(Task task) {
showEditTaskDialog(task);
}
@Override
public void onTaskLongClick(Task task) {
showDeleteDialog(task);
}
@Override
public void onTaskCheckChange(Task task, boolean isChecked) {
task.setCompleted(isChecked);
databaseHelper.updateTask(task);
loadTasks();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_clear_completed) {
clearCompletedTasks();
return true;
} else if (id == R.id.action_delete_all) {
deleteAllTasks();
return true;
}
return super.onOptionsItemSelected(item);
}
private void clearCompletedTasks() {
for (Task task : new ArrayList<>(taskList)) {
if (task.isCompleted()) {
databaseHelper.deleteTask(task.getId());
}
}
loadTasks();
Toast.makeText(this, "已完成的任务已清理", Toast.LENGTH_SHORT).show();
}
private void deleteAllTasks() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("清空任务")
.setMessage("确定要删除所有任务吗?此操作不可恢复!")
.setPositiveButton("确定", (dialog, which) -> {
for (Task task : new ArrayList<>(taskList)) {
databaseHelper.deleteTask(task.getId());
}
loadTasks();
Toast.makeText(this, "所有任务已删除", Toast.LENGTH_SHORT).show();
})
.setNegativeButton("取消", null)
.show();
}
}
布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:clipToPadding="false" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="添加任务"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
app:srcCompat="@android:drawable/ic_input_add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
item_task.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="4dp"
app:cardCornerRadius="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<CheckBox
android:id="@+id/checkCompleted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:layout_marginStart="12dp">
<TextView
android:id="@+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/textDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:maxLines="3"
android:ellipsize="end"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/textDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="@color/teal_700"
android:layout_marginTop="8dp" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
dialog_add_task.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/etTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="任务标题"
android:inputType="text"
android:maxLines="1"
android:textSize="16sp" />
<EditText
android:id="@+id/etDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="任务描述(可选)"
android:inputType="textMultiLine"
android:minLines="3"
android:textSize="14sp"
android:layout_marginTop="12dp" />
</LinearLayout>
menu_main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_clear_completed"
android:title="清理已完成"/>
<item
android:id="@+id/action_delete_all"
android:title="删除全部"/>
</menu>
build.gradle 依赖
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'androidx.cardview:cardview:1.0.0'
}
功能特点
- 添加任务:通过浮动按钮添加新任务
- 编辑任务:点击任务卡片进行编辑
- 删除任务:长按任务卡片删除
- 标记完成:通过复选框标记任务完成状态
- 数据持久化:使用SQLite存储数据
- 批量操作:清理已完成、删除全部任务
运行效果
- 主界面显示任务列表
- 每个任务包含标题、描述、创建日期和完成状态
- 支持下拉刷新(可扩展)
- 支持搜索功能(可扩展)
这个案例涵盖了Android开发的核心知识点:Activity生命周期、RecyclerView适配器、SQLite数据库操作、Material Design组件使用、对话框交互等,是一个完整的学习项目。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播