2016-08-23 72 views
1

我已经梳理了解决此stackoverflow,我已经尝试了吨的片段,并一直无法找出问题。无法填充从api调用gridview

因此,我正在关注一个android Udacity课程,并且已经达到了一个要求我使用电影数据库的api调用填充电影海报的GridView的点。 我在这里看到很多其他人在做同样的项目的计算器stackoverflow然而主要区别(可能为什么他们的解决方案没有为我工作)我有,我试图做到这一点与所有主要类在单独的文件,而不是在主要活动中拥有一切或类似的东西。

我已经尝试了所有解决方案为他们工作,如将gridview适配器声明和setadapter移动到asynctask中的onPostExecute的末尾,并且一遍又一遍地修改了我的ImageAdapter类,但是我无法得到它上班。

我的应用程序不会调用API,记录接收到的JSON和所有海报链接,以及将链接正确复制到arraylist;但gridview不填充。

这里是我的代码:

MainActivity.java

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     if (savedInstanceState == null) { 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.container, new GalleryFragment()) 
        .commit(); 
     } 


    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 
} 

ImageAdapter.java

public class ImageAdapter extends BaseAdapter { 

    private final String LOG_TAG = ImageAdapter.class.getSimpleName(); 

    private List<?> mImageList = new ArrayList<>(); 
    private LayoutInflater inflater; 

    public ImageAdapter(LayoutInflater i, List<?> images) { 


     this.mImageList = images; 
     this.inflater = i; 
    } 

    @Override 
    public Object getItem(int position) { 
     return mImageList.get(position); 
    } 

    @Override 
    public int getCount() { 
     return mImageList.size(); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     ImageView imageView; 
     if (convertView == null){ 
      imageView = new ImageView(inflater.getContext()); 
     } else { 
      imageView = (ImageView) convertView; 
     } 

     Log.v(LOG_TAG,"New one: " + mImageList.get(position).toString()); 

     Picasso 
       .with(inflater.getContext()) 
       .load(mImageList.get(position).toString()) 
       .into(imageView); 
     imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
     imageView.setAdjustViewBounds(true); 

     return imageView; 
    } 
} 

GalleryFragment.java

public class GalleryFragment extends Fragment { 

    public static GridView gridView; 
    public static ImageAdapter imageAdapter; 

    public GalleryFragment() { 
     // Required empty public constructor 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 
     FetchMovies data = new FetchMovies(getActivity()); 
     data.execute(); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setHasOptionsMenu(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_gallery, container, false); 

     gridView = (GridView) rootView.findViewById(R.id.gridview); 

     return rootView; 
    } 
} 

FetchMovies.java

public class FetchMovies extends AsyncTask <Void, Void, String[]> { 

    private final String LOG_TAG = FetchMovies.class.getSimpleName(); 

    private Context context; 
    List<Uri> posterURLs = new ArrayList<>(); 
    String[] title, overview, popularity, rating, releaseDate; 

    public FetchMovies(Context c){ 
     this.context = c; 
    } 





    /** 
    * Prepare image URL for presentation. 
    */ 
    private String formatURL(String relativeURL) { 
     String imageBaseURL = "http://image.tmdb.org/t/p/"; 
     String size = "w185"; 
     relativeURL = relativeURL.substring(1); 
     Uri uri = Uri.parse(imageBaseURL).buildUpon() 
       .appendPath(size) 
       .appendPath(relativeURL).build(); 
     return uri.toString(); 
    } 


    private String[] getMovieDataFromJson(String movieJsonStr) 
      throws JSONException { 

     // These are the names of the JSON objects that need to be extracted. 
     final String RESULT_LIST = "results"; 
     final String TITLE = "original_title"; 
     final String POSTER_URL = "poster_path"; 
     final String OVERVIEW = "overview"; 
     final String POPULARITY = "popularity"; 
     final String RATING = "vote_average"; 
     final String RELEASE_DATE = "release_date"; 

     JSONObject allMovieData = new JSONObject(movieJsonStr); 
     JSONArray resultsArray = allMovieData.getJSONArray(RESULT_LIST); 

     String[] posterPaths = new String[resultsArray.length()]; 
     title = new String[resultsArray.length()]; 
     overview = new String[resultsArray.length()]; 
     popularity = new String[resultsArray.length()]; 
     rating = new String[resultsArray.length()]; 
     releaseDate = new String[resultsArray.length()]; 

     for(int i = 0; i < resultsArray.length(); i++) { 

      // Get the JSON object representing one movie's details 
      JSONObject eachMovie = resultsArray.getJSONObject(i); 

      title[i] = eachMovie.getString(TITLE); 
      String relativeURL = eachMovie.getString(POSTER_URL); 
      posterPaths[i] = formatURL(relativeURL); 
      overview[i] = eachMovie.getString(OVERVIEW); 
      popularity[i] = eachMovie.getString(POPULARITY); 
      rating[i] = eachMovie.getString(RATING); 
      releaseDate[i] = eachMovie.getString(RELEASE_DATE); 
      Log.v("poster path", posterPaths[i]); 
     } 

     return posterPaths; 

    } 


    @Override 
    protected String[] doInBackground(Void... params) { 
     HttpURLConnection urlConnection = null; 
     BufferedReader reader = null; 

     //For building the URL for the weather query from OpenWeatherMap 
     final String BASE_URL = "http://api.themoviedb.org/3/discover/movie?"; 
     final String SORT_PARAM = "sort_by"; 
     final String API_PARAM = "api_key"; 

     String sort_by = "popularity.desc", 
       apiKey = "MY API KEY IS PLACED HERE"; 

     // Will contain the raw JSON response as a string. 
     String movieJsonStr = null; 

     try { 
      // Construct the URL for the OpenWeatherMap query 
      // Possible parameters are available at OWM's forecast API page, at 
      // http://openweathermap.org/API#forecast 
      Uri queryUri = Uri.parse(BASE_URL).buildUpon() 
        //.appendQueryParameter(SORT_PARAM,params[0]) 
        .appendQueryParameter(SORT_PARAM, sort_by) 
        .appendQueryParameter(API_PARAM,apiKey).build(); 

      URL queryUrl = new URL(queryUri.toString()); 
      // Create the request to TheMovieDB, and open the connection 
      urlConnection = (HttpURLConnection) queryUrl.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      urlConnection.connect(); 

      // Read the input stream into a String 
      InputStream inputStream = urlConnection.getInputStream(); 
      StringBuffer buffer = new StringBuffer(); 
      if (inputStream == null) { 
       Log.v(LOG_TAG, "Couldn't open input stream."); 
       // Nothing to do. 
       return null; 
      } 
      reader = new BufferedReader(new InputStreamReader(inputStream)); 

      String line; 
      while ((line = reader.readLine()) != null) { 
       // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) 
       // But it does make debugging a *lot* easier if you print out the completed 
       // buffer for debugging. 
       buffer.append(line + "\n"); 
      } 

      if (buffer.length() == 0) { 
       Log.v(LOG_TAG, "Input stream was empty."); 
       // Stream was empty. No point in parsing. 
       return null; 
      } 

      //if all's well, parse the required data and return it to the system 
      //(which then calls the onPostExecute() method with this data). 
      movieJsonStr = buffer.toString(); 
      Log.v(LOG_TAG,movieJsonStr); 
      return getMovieDataFromJson(movieJsonStr); 
      //return getWeatherDataFromJson(forecastJsonStr, numDays); 

     } catch (IOException e) { 
      Log.e(LOG_TAG, "Error: Couldn't get movie data. ", e); 
      // If the code didn't successfully get the weather data, there's no point in attempting 
      // to parse it. 
      return null; 
     } catch (JSONException e) { 
      Log.e(LOG_TAG, "Error in parsing: ", e); 
      //If there is an error in parsing the JSON data, there's nothing to display. 
      return null; 
     } 
     finally 
     { 
      if (urlConnection != null) { 
       urlConnection.disconnect(); 
      } 
      if (reader != null) { 
       try { 
        reader.close(); 
       } catch (final IOException e) { 
        Log.e(LOG_TAG, "Error closing stream", e); 
       } 
      } 
     } 

    } 

    @Override 
    protected void onPostExecute(String[] strings) { 
     super.onPostExecute(strings); 

     for (int i=0; i<strings.length;i++){ 
      Uri uri = Uri.parse(strings[i]); 
      posterURLs.add(uri); 
     } 

     LayoutInflater inflater = LayoutInflater.from(context); 
     GalleryFragment.imageAdapter = new ImageAdapter(inflater,posterURLs); 

     GalleryFragment.gridView.setAdapter(GalleryFragment.imageAdapter); 


    } 


} 

这里是我的布局文件:

fragment_gallery.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.zakna.popularmovies.GalleryFragment"> 


    <GridView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/gridview" 
     android:layout_gravity="start|top" 
     android:numColumns="auto_fit" 
     android:clickable="false" /> 

</FrameLayout> 

gallery_grid_item.xml

<ImageView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/movie_poster"> 

</ImageView> 

activity_main.xml中

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    tools:context="com.example.zakna.popularmovies.MainActivity"> 

    <android.support.design.widget.AppBarLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/AppTheme.AppBarOverlay"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:background="?attr/colorPrimary" 
      app:popupTheme="@style/AppTheme.PopupOverlay" /> 

    </android.support.design.widget.AppBarLayout> 

    <include layout="@layout/content_main" /> 

</android.support.design.widget.CoordinatorLayout> 

content_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" 
    android:layout_width="match_parent" android:layout_height="match_parent" 
    tools:context=".MainActivity" tools:ignore="MergeRootFrame" /> 

logcat的输出:

W/System: ClassLoader referenced unknown path: /data/app/com.example.zakna.popularmovies-1/lib/arm64 
W/System: ClassLoader referenced unknown path: /data/app/com.example.zakna.popularmovies-1/lib/arm64 
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable 
I/DpmTcmClient: RegisterTcmMonitor from: com.android.okhttp.TcmIdleTimerMonitor 
D/AppTracker: App Event: start 
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true 
I/Adreno: QUALCOMM build     : 183c040, Iff84fb1103 
                     Build Date      : 03/18/16 
                     OpenGL ES Shader Compiler Version: XE031.06.00.02 
                     Local Branch      : 
                     Remote Branch     : refs/tags/AU_LINUX_ANDROID_LA.BF64.1.2.2_RB4.06.00.01.180.031 
                     Remote Branch     : NONE 
                     Reconstruct Branch    : NOTHING 
I/OpenGLRenderer: Initialized EGL, version 1.4 
D/AbstractTracker: Event success 
V/FetchMovies: SNIPPED JSON FILE 
V/poster path: http://image.tmdb.org/t/p/w185/e1mjopzAS2KNsvpbpahQ1a6SkSn.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/lFSSLTlFozwpaGlO31OoUeirBgQ.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/vOipe2myi26UDwP978hsYOrnUWC.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/cGOPbv9wA5gEejkUN892JrveARt.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/kqjL17yufvn9OVLyXYpvtyrFfak.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/5N20rQURev5CNDcMjHVUZhpoCNC.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/h28t2JNNGrZx0fIuAw8aHQFhIxR.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/uANwnNNlX4DfUoA6UurzyoAAxTj.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/4qnJ1hsMADxzwnOmnwjZTNp0rKT.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/gj282Pniaa78ZJfbaixyLXnXEDI.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/jjBgi2r5cRt36xF6iNUEhzscEcb.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/vNCeqxbKyDHL9LUza03V2Im16wB.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/5JU9ytZJyR3zmClGmVm9q4Geqbd.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/ghL4ub6vwbYShlqCFHpoIRwx2sm.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/dCgm7efXDmiABSdWDHBDBx2jwmn.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/inVq3FRqcYIRl2la8iZikYYxFNR.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/nBNZadXqJSdt05SHLqgT0HuC5Gm.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/sM33SANp9z6rXW8Itn7NnG1GOEs.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/aBBQSC8ZECGn6Wh92gKDOakSC8p.jpg 
V/poster path: http://image.tmdb.org/t/p/w185/t2mZzQXjpQxmqtJOPpe8Dr2YpMl.jpg 
V/ImageAdapter: New one: http://image.tmdb.org/t/p/w185/e1mjopzAS2KNsvpbpahQ1a6SkSn.jpg 
W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value. 
W/IInputConnectionWrapper: getExtractedText on inactive InputConnection 
W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection 
W/IInputConnectionWrapper: getSelectedText on inactive InputConnection 
W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection 
D/AppTracker: App Event: stop 
D/AbstractTracker: Event success 

我的日志还显示我的ImageAdapter类只调用一次。它不应该被称为多次,因为它填充gridview? 在这一点上,我很确信这个问题与布局文件有关,也许我没有在正确的地方调用正确的地方或类似的东西,但我无法弄清楚。帮助将不胜感激,谢谢!

+0

你有权限吗? –

+0

我有清单文件中的Internet权限。 <使用权限android:name =“android.permission.INTERNET”/> 我需要任何其他权限吗? –

+0

也许有存储权限? –

回答

0

我终于找到了问题。就像我想的那样,这是显而易见的,我忽略了布局。

fragment_gallery.xml我:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.zakna.popularmovies.GalleryFragment"> 


    <GridView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/gridview" 
     android:layout_gravity="start|top" 
     android:numColumns="auto_fit" 
     android:clickable="false" /> 

</FrameLayout> 

的问题是,android:layout_widthandroid:layout_height 分别设置为 “WRAP_CONTENT” 时,他们应该被设置为 “match_parent”。

因此该解决方案是改变fragment_gallery.xml到:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.zakna.popularmovies.GalleryFragment"> 

    <GridView 
     android:id="@+id/gridview" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:numColumns="auto_fit" 
     android:layout_gravity="start|top" 
     android:clickable="false" /> 
</FrameLayout> 

,现在我的应用程序正确地显示在GridView中的所有图像。

谢谢!