커뮤니티
포인트
쿠폰
내 강의실
국비 신청 내역
증명서
계정
로그아웃
학습 질문
개발 일지
나의 활동
답변 완료
launch emulator 실행이 안됩니다.
앱개발 종합반 - 플러터 v8
0주차
북마크
장*만
댓글
1
추천
0
조회수
12
조회수
12
답변 완료

* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.

* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.


debug console

Launching lib\main.dart on Chrome in debug mode...

Launching lib\main.dart on Windows in debug mode...

main.dart:1

Exception: Building with plugins requires symlink support.


Please enable Developer Mode in your system settings. Run

start ms-settings:developers

to open settings.



고 계

신 화면 전체를 캡처해 주시면, 튜터님들이 빠르게 상황을 이해할 수 있어요.




작성한 코드 및 에러 메세지

오류 // ignore_for_file: must_be_immutable


import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'package:webview_flutter/webview_flutter.dart';


import 'book.dart';

import 'book_service.dart';


void main() {

 runApp(

  MultiProvider(

   providers: [

    ChangeNotifierProvider(create: (context) => BookService()),

   ],

   child: const MyApp(),

  ),

 );

}


class MyApp extends StatelessWidget {

 const MyApp({Key? key}) : super(key: key);


 @override

 Widget build(BuildContext context) {

  return MaterialApp(

   debugShowCheckedModeBanner: false,

   home: HomePage(),

  );

 }

}


class HomePage extends StatefulWidget {

 const HomePage({Key? key}) : super(key: key);


 @override

 State<HomePage> createState() => _HomePageState();

}


class _HomePageState extends State<HomePage> {

 var bottomNavIndex = 0;

 @override

 Widget build(BuildContext context) {

  return Scaffold(

   body: [

    SearchPage(),

    LikedBookPage(),

   ].elementAt(bottomNavIndex),

   bottomNavigationBar: BottomNavigationBar(

    selectedItemColor: Colors.black,

    unselectedItemColor: Colors.grey,

    showUnselectedLabels: true,

    selectedFontSize: 12,

    unselectedFontSize: 12,

    iconSize: 28,

    type: BottomNavigationBarType.fixed,

    onTap: (value) {

     setState(() {

      bottomNavIndex = value;

     });

    },

    items: [

     BottomNavigationBarItem(

      icon: Icon(Icons.search),

      label: '검색',

     ),

     BottomNavigationBarItem(

      icon: Icon(Icons.star),

      label: '좋아요',

     ),

    ],

    currentIndex: bottomNavIndex,

   ),

  );

 }

}


class SearchPage extends StatelessWidget {

 const SearchPage({super.key});


 @override

 Widget build(BuildContext context) {

  return Consumer<BookService>(

   builder: (context, bookService, child) {

    return Scaffold(

     appBar: AppBar(

      backgroundColor: Colors.white,

      toolbarHeight: 80,

      title: TextField(

       onSubmitted: (value) {

        bookService.search(value);

       },

       cursorColor: Colors.grey,

       decoration: InputDecoration(

        prefixIcon: Icon(Icons.search, color: Colors.grey),

        hintText: "작품, 감독, 배우, 컬렉션, 유저 등",

        border: OutlineInputBorder(

         borderSide: BorderSide(color: Colors.white),

         borderRadius: BorderRadius.all(Radius.circular(10)),

        ),

        focusedBorder: OutlineInputBorder(

         borderSide: BorderSide(color: Colors.grey),

         borderRadius: BorderRadius.all(Radius.circular(10)),

        ),

       ),

      ),

     ),

     body: Padding(

      padding: const EdgeInsets.symmetric(horizontal: 12),

      child: ListView.separated(

       itemCount: bookService.bookList.length,

       separatorBuilder: (context, index) {

        return Divider();

       },

       itemBuilder: (context, index) {

        if (bookService.bookList.isEmpty) return SizedBox();

        Book book = bookService.bookList.elementAt(index);

        return BookTile(book: book);

       },

      ),

     ),

    );

   },

  );

 }

}


class BookTile extends StatelessWidget {

 const BookTile({

  Key? key,

  required this.book,

 }) : super(key: key);


 final Book book;


 @override

 Widget build(BuildContext context) {

  BookService bookService = context.read<BookService>();


  return ListTile(

   onTap: () {

    Navigator.push(

     context,

     MaterialPageRoute(

      builder: (context) => WebViewPage(

       url: book.previewLink.replaceFirst("http", "https"),

      ),

     ),

    );

   },

   leading: Image.network(

    book.thumbnail,

    fit: BoxFit.fitHeight,

   ),

   title: Text(

    book.title,

    style: TextStyle(fontSize: 16),

   ),

   subtitle: Text(

    "${book.authors.join(", ")}\n${book.publishedDate}",

    style: TextStyle(color: Colors.grey),

   ),

   trailing: IconButton(

    onPressed: () {

     bookService.toggleLikeBook(book: book);

    },

    icon: bookService.likedBookList.map((book) => book.id).contains(book.id)

      ? Icon(

        Icons.star,

        color: Colors.amber,

       )

      : Icon(Icons.star_border),

   ),

  );

 }

}


class LikedBookPage extends StatelessWidget {

 const LikedBookPage({super.key});


 @override

 Widget build(BuildContext context) {

  return Consumer<BookService>(

   builder: (context, bookService, child) {

    return Scaffold(

     body: Padding(

      padding: const EdgeInsets.symmetric(horizontal: 12),

      child: ListView.separated(

       itemCount: bookService.likedBookList.length,

       separatorBuilder: (context, index) {

        return Divider();

       },

       itemBuilder: (context, index) {

        if (bookService.likedBookList.isEmpty) return SizedBox();

        Book book = bookService.likedBookList.elementAt(index);

        return BookTile(book: book);

       },

      ),

     ),

    );

   },

  );

 }

}


class WebViewPage extends StatefulWidget {

 WebViewPage({super.key, required this.url});


 String url;


 @override

 State<WebViewPage> createState() => _WebViewPageState();

}


class _WebViewPageState extends State<WebViewPage> {

 @override

 Widget build(BuildContext context) {

  return Scaffold(

   appBar: AppBar(

    backgroundColor: Colors.grey,

    title: Text(widget.url),

   ),

   body: WebView(initialUrl: widget.url),

  );

 }

}

발생 시, 작성한 코드 전체와 에러 메시지를 첨부해 주세요.

class Book {

 String id;

 String title;

 String subtitle;

 List authors;

 String publishedDate;

 String thumbnail; // 썸네일 이미지 링크

 String previewLink; // ListTile 을 눌렀을 때 이동하는 링크


 Book({

  required this.id,

  required this.title,

  required this.subtitle,

  required this.authors,

  required this.publishedDate,

  required this.thumbnail,

  required this.previewLink,

 });

}


import 'package:dio/dio.dart';

import 'package:flutter/material.dart';


import 'book.dart';


class BookService extends ChangeNotifier {

 List<Book> bookList = []; // 책 목록

 List<Book> likedBookList = [];


 void toggleLikeBook({required Book book}) {

  String bookId = book.id;

  if (likedBookList.map((book) => book.id).contains(bookId)) {

   likedBookList.removeWhere((book) => book.id == bookId);

  } else {

   likedBookList.add(book);

  }

  notifyListeners();

 }


 void search(String q) async {

  bookList.clear(); // 검색 버튼 누를때 이전 데이터들을 지워주기


  if (q.isNotEmpty) {

   Response res = await Dio().get(

    "https://www.googleapis.com/books/v1/volumes?q=$q&startIndex=0&maxResults=40",

   );

   List items = res.data["items"];


   for (Map<String, dynamic> item in items) {

    Book book = Book(

     id: item['id'],

     title: item['volumeInfo']['title'] ?? "",

     subtitle: item['volumeInfo']['subtitle'] ?? "",

     authors: item['volumeInfo']['authors'] ?? [],

     publishedDate: item['volumeInfo']['publishedDate'] ?? "",

     thumbnail: item['volumeInfo']['imageLinks']?['thumbnail'] ??

       "https://thumbs.dreamstime.com/b/no-image-available-icon-flat-vector-no-image-available-icon-flat-vector-illustration-132482953.jpg",

     previewLink: item['volumeInfo']['previewLink'] ?? "",

    );

    bookList.add(book);

   }

  }

  notifyListeners();

 }

}

Tip 1) </> 아이콘을 눌러 코드박스를 만들어 보세요.

Tip 2) Ctrl+A(맥의 경우 Command+A) 단축키로 코드를 한 번에 선택할 수 있어요!



취소
 공유
취소
댓글 0
댓글 알림
나의얼굴