为什么我们使用界面在MainActivity中为回收者视图设置onClick for View Holders

时间:2017-08-25 20:54:36

标签: java android

我正在阅读一个教程,该教程使用Recycler View来显示一周内每天的天气列表。 有两个类我很困惑:

  

ForecastAdapter和MainActivity

以下是上述两个类的代码:

  

ForecastAdapter.java

public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.ForecastAdapterViewHolder> {

    private String[] mWeatherData;
    final private ForecastAdapterOnClickListener mClickHandler;

    //Why do we need to create an interface here.
    public interface ForecastAdapterOnClickListener {
        void onClick(String weatherForDay);
    }

    public ForecastAdapter(ForecastAdapterOnClickListener forecastAdapterOnClickListener) {
        mClickHandler = forecastAdapterOnClickListener;
    }


    public class ForecastAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        public final TextView mWeatherTextView;

        public ForecastAdapterViewHolder(View view) {
            super(view);
            mWeatherTextView = (TextView) view.findViewById(R.id.tv_weather_data);
            view.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int adapterPosition = getAdapterPosition();
            String weatherForDay = mWeatherData[adapterPosition];

            //Why are we calling onClick from mClickHandler here. Why can't we just display Toast here. 
            mClickHandler.onClick(weatherForDay); 

            /*Why can't we just display the Toast from here like this:
              Toast.makeText(v.getContext(), weatherForDay, Toast.LENGTH_SHORT).show()
            */
        }

    }


    @Override
    public ForecastAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        Context context = viewGroup.getContext();
        int layoutIdForListItem = R.layout.forecast_list_item;
        LayoutInflater inflater = LayoutInflater.from(context);
        boolean shouldAttachToParentImmediately = false;

        View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
        return new ForecastAdapterViewHolder(view);
    }


    @Override
    public void onBindViewHolder(ForecastAdapterViewHolder forecastAdapterViewHolder, int position) {
        String weatherForThisDay = mWeatherData[position];
    forecastAdapterViewHolder.mWeatherTextView.setText(weatherForThisDay);
    }


    @Override
    public int getItemCount() {
        if (null == mWeatherData) return 0;
        return mWeatherData.length;
    }


    public void setWeatherData(String[] weatherData) {
        mWeatherData = weatherData;
        notifyDataSetChanged();
    }
}




  

MainActivity.java

//Why are implementing ForecastAdapterOnClickListener here?
public class MainActivity extends AppCompatActivity implements ForecastAdapter.ForecastAdapterOnClickListener{

private RecyclerView mRecyclerView;
private ForecastAdapter mForecastAdapter;

private TextView mErrorMessageDisplay;

private ProgressBar mLoadingIndicator;

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

    mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview_forecast);
    mErrorMessageDisplay = (TextView) findViewById(R.id.tv_error_message_display);

    LinearLayoutManager layoutManager
            = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);

    mRecyclerView.setLayoutManager(layoutManager);


    mRecyclerView.setHasFixedSize(true);


    mForecastAdapter = new ForecastAdapter(this);
    mRecyclerView.setAdapter(mForecastAdapter);


    mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);

    loadWeatherData();
}


private void loadWeatherData() {
    showWeatherDataView();

    String location = SunshinePreferences.getPreferredWeatherLocation(this);
    new FetchWeatherTask().execute(location);
}


@Override
public void onClick(String weatherForDay) {
    Context context = this;
    Toast.makeText(context, weatherForDay, Toast.LENGTH_SHORT)
            .show();
}


private void showWeatherDataView() {
    mErrorMessageDisplay.setVisibility(View.INVISIBLE);
    mRecyclerView.setVisibility(View.VISIBLE);
}


private void showErrorMessage() {
    mRecyclerView.setVisibility(View.INVISIBLE);
    mErrorMessageDisplay.setVisibility(View.VISIBLE);
}

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

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mLoadingIndicator.setVisibility(View.VISIBLE);
    }

    @Override
    protected String[] doInBackground(String... params) {
        if (params.length == 0) {
            return null;
        }

        String location = params[0];
        URL weatherRequestUrl = NetworkUtils.buildUrl(location);

        try {
            String jsonWeatherResponse = NetworkUtils
                    .getResponseFromHttpUrl(weatherRequestUrl);

            String[] simpleJsonWeatherData = OpenWeatherJsonUtils
                    .getSimpleWeatherStringsFromJson(MainActivity.this, jsonWeatherResponse);

            return simpleJsonWeatherData;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(String[] weatherData) {
        mLoadingIndicator.setVisibility(View.INVISIBLE);
        if (weatherData != null) {
            showWeatherDataView();
            mForecastAdapter.setWeatherData(weatherData);
        } else {
            showErrorMessage();
        }
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.forecast, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.action_refresh) {
        mForecastAdapter.setWeatherData(null);
        loadWeatherData();
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

适配器,视图持有者和回收者视图正在按预期工作。我们现在应该在回收器视图的行上实现Click Handling。每当点击一个特定的行时,我们应该显示一个祝酒词。

如您所见,我们在ForecastAdapterViewHolder中实现了OnClickListener,在onClick函数中我们调用了接口“ForecastAdapterOnClickListener”的onClick。 在MainActivity.java中,我们正在实现这个“ForecastAdapterOnClickListener”,然后显示toast。

为什么我们不能只在为“ForecastAdapterViewHolder”类定义的onClick中显示toast。我试过了它,它的工作原理。在代码中执行的操作有什么意义? 设置点击监听器是否有一些优势?

1 个答案:

答案 0 :(得分:0)

因为您必须在之后显示信息,而不是ViewHolder的角色,也不是适配器。活动/片段必须这样做。 这是为了保持你的代码有条理。