Skip to content

知乎小报开发总结

marktony edited this page Apr 26, 2016 · 1 revision

知乎小报开发总结

总结在知乎小报开发的工程中遇到的问题以及相关的解决办法。

1.Intent导致的ActivityNotFoundException

无法找到对应的activity,这个异常在使用Intent启动一些系统级隐式的activity时可能会出现,例如短信、邮件、打开相机等,(还有手机没有邮件、短信app?当然有了!)如果不对这个异常进行处理的话,应用就会直接Crash。

Uri uri = Uri.parse("market://details?id="+getPackageName());
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

这个异常在开发简单翻译的过程就曾经遇到过。

  • 方法1: 最佳解决方案-->在发出这个隐式Intent之前调用resolveActivity做检查

    Intent intent = new Intent(Intent.ACTION_XXX);
    ComponentName componentName = intent.resolveActivity(getPackageManager());
    if(componentName != null) {
    String className = componentName.getClassName();
    }
    
  • 方法2:使用try-catch捕获这个异常。

    try{
    // to start a mail activity code
    } catch (android.content.ActivityNotFoundException ex){
    // catch Exception
    Snackbar.make(view, "No mail app found",Snackbar.LENGTH_SHORT).show();
    }
    

2.WebView无图模式的实现

Android WebView中实现了一个方法

webView.getSettings().setBlockNetworkImage(boolean config)

官方文档解释为:

Gets whether the WebView does not load image resources from the network.

当config为true时,不加载图片,反之加载图片,而且是当url加载完成时才开始加载。

3.接口实现RecyclerView item的点击事件 RecyclerView是Google在v7包中新增的一种控件,用于代替ListView,不过它并没有基本的点击事件,所以需要我们自己为item定义点击事件。

首先需要自定义接口

public interface OnRecyclerViewOnClickListener {
    void OnItemClick(View v,int position);
}

在适配器中定义接口变量

private OnRecyclerViewOnClickListener mListener;

暴露接口

public void setItemClickListener(OnRecyclerViewOnClickListener listener){
    this.mListener = listener;
}

然后在onCreateViewHolder中注册点击事件

@Override
public LatestItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = inflater.inflate(R.layout.latest_item_layout,parent,false);
    LatestItemViewHolder holder = new LatestItemViewHolder(view,mListener);
    return holder;
}

在ViewHolder中设置

public class LatestItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private OnRecyclerViewOnClickListener listener;
    private CardView item;

    public LatestItemViewHolder(View itemView,OnRecyclerViewOnClickListener listener) {
        super(itemView);

        item = (CardView) itemView.findViewById(R.id.card_view_item);
        this.listener = listener;
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (listener != null){
            listener.OnItemClick(v,getLayoutPosition());
        }
    }
}

在Activity或者Fragment中使用

adapter = new LatestPostAdapter(getActivity(),list);
rvLatestNews.setAdapter(adapter);
adapter.setItemClickListener(new OnRecyclerViewOnClickListener() {
    @Override
    public void OnItemClick(View v, int position) {
        // write code
    }
});

4.横屏下Crash 由于在fragment中使用了RecyclerView,当然也就涉及到了Adapoter的使用。由于我在Adapter的构造函数中传入了Context,这直接导致了横屏下直接崩溃。

public class LatestPostAdapter extends RecyclerView.Adapter<LatestPostAdapter.LatestItemViewHolder> {
// some code
public LatestPostAdapter(Context context, List<LatestPost> list){
      this.context = context;
      this.list = list;
      this.inflater = LayoutInflater.from(context);
  }
}

我们不应该保存那些依赖Activity的数据,比如Drawable,Adapter,View或者任何与Context相关联的数据。因为上一个Activity已经没有了,如果你还要保持这些资源的引用,可能导致资源泄露。

解决的方法

  • 1.简单粗暴型 直接禁止横屏,当然这只是适用于极少数的情况。可以在manifest文件中对应的activity配置:

    android:screenOrientation="portrait" android:screenOrientation="landscape"

或者在Java代码中处理

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
  • 2.在横屏时做相应的处理。 首先在manifest.xml文件中配置屏幕方向改变时不需要重新载入。

然后在activity中重写方法

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

5.toolbar中小箭头(返回上级activity) 好吧,这是个不算高级的问题,但是确实困扰了我一段时间。首先是怎样显示这个箭头。

private Toolbar toolbar;
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// 关键
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

怎样监听小箭头的点击事件呢?

由于箭头是位于toolbar中的控件,可以联想到应该是和onOptionsItemSelected方法有关。

@Override
public boolean onOptionsItemSelected(MenuItem item) {

   int id = item.getItemId();

   // 小箭头的id为android.R.id.home
   if (id == android.R.id.home){
       onBackPressed();
   }

   return super.onOptionsItemSelected(item);
 }

当我满怀信心写完这些代码,运行到手机上的时候,点击箭头,竟然没有返回。。。这是因为没有在manifest.xml文件中配置他的上一级activity是什么,所以也就没有返回了。配置好之后就可以正常运行了。

Clone this wiki locally