سلام وقت بخیر
من میخوام یک صفحه سرچ بزنم که با تغیر مقدار داخل یک تکس فیلد درخواستی یه سرور بفرسته و لیست کتاب هارو بگیره با ارگومنت onChanged استفاده میکنم مشکلی که هست وقتی متن داخل تکس فیلد رو پاک میکنم باید EmptyStateنشون بده ولی یک لیست نشون میده چون موقع پاک کردن بازم درخواست میفرسته و یکم طول میکشه تا جواب درخواستها بیاد وزمانی که جواب درخواست میا یک SuccessStateمیفرسته
اگه راه حلی بهم بدین ممنون میشم
class SearchScreen extends StatefulWidget {
const SearchScreen({super.key});
@override
State<SearchScreen> createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
final TextEditingController _searchControler = TextEditingController();
SearchBloc? searchBloc;
@override
void dispose() {
// TODO: implement dispose
searchBloc?.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: BlocProvider<SearchBloc>(
create: (context) {
final bloc = SearchBloc(bookRepo)..add(SearchStarted());
searchBloc=bloc;
return bloc;
},
child: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context).dividerColor,
),
width: MediaQuery.of(context).size.width,
height: 75,
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
color: LiightThemeColors.secondaryTextColor
.withOpacity(0.4),
borderRadius: BorderRadius.circular(5),
),
height: 56,
margin: const EdgeInsets.fromLTRB(12, 0, 12, 0),
child: TextField(
controller: _searchControler,
onChanged: (value) {
searchBloc!.add(SearchChangeSearchTerm(value));
},
// textInputAction: TextInputAction.search,
decoration: InputDecoration(
labelText: 'جستجو',
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide.none),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide.none),
prefixIcon: IconButton(
onPressed: () {},
icon: const Padding(
padding: EdgeInsets.only(right: 8.0),
child: Icon(CupertinoIcons.search),
)),
floatingLabelBehavior: FloatingLabelBehavior.never,
),
),
),
),
Container(
margin: const EdgeInsets.only(left: 12),
child: GestureDetector(
child:
SvgPicture.asset('assets/icons/library_icon.svg'),
onTap: () {},
))
],
),
),
BlocBuilder<SearchBloc, SearchState>(
builder: (context, state) {
return Expanded(
child: state is SerchSuccessState
? _BookList(bookList: state.bookList)
: state is SearchEmptyState
? Center(child: Text(state.text))
: state is SearchErrorState
? const Center(
child: Text("error"),
)
: state is SearchLoadingState
? const Center(
child: CupertinoActivityIndicator(),
)
: throw Exception('not supported'));
},
),
],
),
),
),
);
}
}
class _BookList extends StatelessWidget {
const _BookList({super.key, required this.bookList});
final List<BookEntity2> bookList;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: bookList.length,
itemBuilder: (context, index) {
return Container(
width: MediaQuery.of(context).size.width,
height: 80,
child: Text(bookList[index].name),
);
});
}
}
کدهای bloc
class SearchBloc extends Bloc<SearchEvent, SearchState> {
final IBookRepository bookRepository;
SearchBloc(this.bookRepository) : super(SearchLoadingState()) {
on<SearchEvent>((event, emit) async {
if (event is SearchStarted) {
emit(SearchLoadingState());
emit(SearchEmptyState('کتاب مورد نظر را جستجو کنید'));
} else if (event is SearchChangeSearchTerm) {
if(event.searchTerm.isNotEmpty){
emit(SearchLoadingState());
try {
final bookList =
await bookRepository.searchForDownload(event.searchTerm);
emit(SerchSuccessState(bookList));
} catch (e) {
emit(SearchErrorState());
}
}else{
emit(SearchEmptyState('کتاب مورد نظر را سرچ کنید'));
}
}
});
}
}