如何在recyclerview gridlayout

时间:2016-12-23 17:12:28

标签: android android-asynctask android-recyclerview adapter

我是Android的新手,并尝试更新udacity nanodegree项目的热门电影应用中的gridlayout

我正在使用AsyncTask下载数据并解析数据,更新recyclerview并在onPostExecute中设置适配器。

这是我的AsyncTask类

private class getJson extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... strings) {
        String result = "";
        URL url;
        HttpURLConnection httpURLConnection = null;


        try {
            url = new URL(strings[0]);

            httpURLConnection = (HttpURLConnection) url.openConnection();

            InputStream in = httpURLConnection.getInputStream();

            InputStreamReader reader = new InputStreamReader(in);

            int data = reader.read();

            while ( data != -1 ){
                  char current  = (char) data;

                  result += current;

                  data = reader.read();
            }

        } catch (java.io.IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        jsonString = s;

        Log.i("result", jsonString);

        JSONObject jsonObject = null;

        if(!list.isEmpty())
          list.clear();
        try {

            jsonObject = new JSONObject(jsonString);

            JSONArray jsonArray = jsonObject.getJSONArray("results");

            for( int i = 0; i < jsonArray.length() && i < 10; i++ ){

                JSONObject currObject = jsonArray.getJSONObject(i);

                String posterurl = preUrl + currObject.getString("backdrop_path");

                Log.i("poster", posterurl);

                String url =  preUrl + currObject.getString("poster_path");

                String overview = currObject.getString("overview");

                String title = currObject.getString("original_title");

                String release_date = (currObject.getString("release_date"));

                String votes = (currObject.getString("vote_average"));

                list.add(new MovieDetails(url,overview, title, release_date, votes, posterurl));
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }



    }
}

这是我的适配器类

    public class MainRecyclerViewAdapter extends RecyclerView.Adapter<MainRecyclerViewAdapter.ViewHolder> {

    ArrayList<MovieDetails> data;
    Context context;

    public MainRecyclerViewAdapter(Context context, ArrayList<MovieDetails> data ){
         this.data = data;
         this.context = context;
    }
    @Override
    public MainRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);

        MainRecyclerViewAdapter.ViewHolder viewHolder = new MainRecyclerViewAdapter.ViewHolder(v);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(MainRecyclerViewAdapter.ViewHolder holder, int position) {

        Picasso.with(context).load(data.get(position).getImageUrl()).into(holder.movie_thumbnail);
        //holder.movie_thumbnail.setImageResource(R.mipmap.ic_launcher);


    }

    @Override
    public int getItemCount() {
       return data.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        ImageView movie_thumbnail;

        private Context context;

        @Override
        public void onClick(View view) {
            Toast.makeText(context,data.get(getPosition()).getTitle(),Toast.LENGTH_LONG).show();
            Intent intent = new Intent(context, DetailsActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable("list", (Serializable) data);
            intent.putExtras(bundle);
            intent.putExtra("index", getAdapterPosition());

            context.startActivity(intent);
        }

        public ViewHolder(View itemView) {
            super(itemView);
            context = itemView.getContext();
            itemView.setOnClickListener(this);
            movie_thumbnail = (ImageView) itemView.findViewById(R.id.movies_item_thumbnail);
        }
    }
}

这就是我根据投票或受欢迎程度处理排序的方式

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    getJson gJson = new getJson();
    switch (item.getItemId()){
        case R.id.rating :
            gJson.execute(top_rated);
            return true;
        case R.id.popularity : gJson.execute(popular);
            return true;
        default: return super.onOptionsItemSelected(item);

    }

}

onCreate

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar myToolbar = (Toolbar) findViewById(R.id.main_toolbar);
    setSupportActionBar(myToolbar);

    getJson getJson = new getJson();
    getJson.execute(popular);

    recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview);

    recyclerView.setHasFixedSize(true);
    layoutManager = new GridLayoutManager(MainActivity.this,2);
    recyclerView.setLayoutManager(layoutManager);

    adapter = new MainRecyclerViewAdapter(MainActivity.this, list);
    recyclerView.setAdapter(adapter);

}

我想要使用notifydatasetchanged(),但我无法想象使用

另请告诉我更好的方式来处理排序。

这就是我所做的:

  1. 我将适配器的实例化和适配器的设置移动到onCreate
  2. notfiydatasetchanged()

  3. 中呼叫onPostexeute()
  4. 每次我调用AsyncTask时,我的arraylist都会填充新的元素,因此适配器正在填充所有图像。在解析list.clear()

  5. 中的json之前,我 onPostexecute()

5 个答案:

答案 0 :(得分:1)

对于 http-requests ,我建议您使用 retrofit 。 适配器描述了所需选项的排序功能,调用它并最终$('.chicken').each(function () { $(this).css('background-image', $(this).css('background-image').replace(".jpg", "@2x.jpg")); });

例如

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="chicken" style="background-image: url('monkey.jpg');"></div>
<div class="chicken" style="background-image: url('donkey.jpg');"></div>
<div class="chicken" style="background-image: url('kitten.jpg');"></div>
<div class="chicken" style="background-image: url('lollol.jpg');"></div>

当您想使用排序时,只需调用排序 notifydatasetchanged();的方法,将数据设置到其中。

答案 1 :(得分:1)

在活动的adapter中设置onCreate

    adapter = new MainRecyclerViewAdapter(MainActivity.this, list);
    recyclerView.setAdapter(adapter);

使用字段存储您的列表。

拨打notifydatasetchanged()的{​​{1}}中的onPostExecute()(就像您正在做的那样),但不要重新分配AsyncTask那里。

答案 2 :(得分:1)

就像Cory Roy suggested一样,试试这个:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview);
        layoutManager = new GridLayoutManager(MainActivity.this, 2);
        recyclerView.setLayoutManager(layoutManager);

        adapter = new MainRecyclerViewAdapter(MainActivity.this, list);
        recyclerView.setAdapter(adapter);
    }

   private class getJson extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... strings) {
        String result = "";
        URL url;
        HttpURLConnection httpURLConnection = null;

        try {
            url = new URL(strings[0]);

            httpURLConnection = (HttpURLConnection) url.openConnection();

            InputStream in = httpURLConnection.getInputStream();

            InputStreamReader reader = new InputStreamReader(in);

            int data = reader.read();

            while ( data != -1 ){
                  char current  = (char) data;

                  result += current;

                  data = reader.read();
            }

        } catch (java.io.IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        jsonString = s;

        Log.i("result", jsonString);

        JSONObject jsonObject = null;
        try {

            jsonObject = new JSONObject(jsonString);

            JSONArray jsonArray = jsonObject.getJSONArray("results");

            for( int i = 0; i < jsonArray.length() && i < 10; i++ ){

                JSONObject currObject = jsonArray.getJSONObject(i);

                String posterurl = preUrl + currObject.getString("backdrop_path");

                Log.i("poster", posterurl);

                String url =  preUrl + currObject.getString("poster_path");

                String overview = currObject.getString("overview");

                String title = currObject.getString("original_title");

                String release_date = (currObject.getString("release_date"));

                String votes = (currObject.getString("vote_average"));

                list.add(new MovieDetails(url,overview, title, release_date, votes, posterurl));
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        adapter.notifyDataSetChanged();

    }
}

请尝试一下,让我知道它是否有效。

答案 3 :(得分:1)

您使用AsyncTask从远程服务器下载电影。下载和解析结束后,您可以创建适配器并将其设置为RecyclerView

根据您的实现,无需在postExecute()

上调用notifyDataSetChanged()

上述方法的一个缺点是,每次AsyncTask执行时都会创建一个新的适配器实例。

尝试下面的内容

 Activity {

    ArrayList<MovieDetails> data;
    MainRecyclerViewAdapter adapter

    onCreate() {

        recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview);

        recyclerView.setHasFixedSize(true);
        layoutManager = new GridLayoutManager(MainActivity.this,2);
        recyclerView.setLayoutManager(layoutManager);


        adapter = new MainRecyclerViewAdapter(MainActivity.this);
        recyclerView.setAdapter(adapter);
    }


    AsyncTask {
        /.....

        onPostExecute{

            // Download completed
            adapter.notifyDataSetChanged()
        }
    }

    MainRecyclerViewAdapter {

        //...
        ViewHolder {
            //...
        }
    }
}

答案 4 :(得分:1)

以下是您需要做的所有事情,

看看我的例子

这些是全球变量

    private List<Movie> movieList = new ArrayList<>();
    private RecyclerView recyclerView;
    private MoviesAdapter mAdapter; 

让我们转到onCreate

1.初始化回收视图

recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

2.创建我的列表的新实例

mAdapter = new MoviesAdapter(movieList);

3.设置我的回收视图

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());

4.将适配器设置为我的recycleView

recyclerView.setAdapter(mAdapter);

5.调用加载数据的方法。

setMyData();

让我们转到setMyData 方法

1.从某种方式获取数据..可能是断断续续的

2.将它们添加到我的列表中

movieList.add(movie); // i have not added the lines where i add data to my movie list think it has 10 elements now 

3.在我添加所有数据后,我执行了

mAdapter.notifyDataSetChanged();

所以每次有变化我都可以调用setMyData();它根据需要设置数据。

那个逻辑怎么样?

故意没有添加Adapter类,如果你需要那个,请告诉我

提示:您的异步任务应该执行setMyData()方法的操作吗?现在看。             好的,你需要第二次更新你的数据!完成异步任务,      layoutManager = new GridLayoutManager(MainActivity.this,2);

啊,当你打电话给你的异步任务时,你一次又一次地调用这一行...人们建议你在onPostExecute notifyDataSet ,(它有效但是..)想想,新的对象也被创建了棕褐色!调用你的asyncTask 10次..现在比较我创建我的对象的地方,是否继续增加..现在你会看到出了什么问题!

p.s我的LayoutManager实例不在我的setMyData()方法中,而在我的onCreate