目前,我正在尝试在 Android 上创建一个文件管理器应用程序,使用片段以方便以后使用。像我一样缺乏经验,我往往会遇到问题,我无法弄清楚这个最新的问题。应用程序的力量在我启动它的那一刻就关闭了。我正在运行 Galaxy Nexus,以防有人想知道。
我在这里使用了一个 Item 类,它基本上只是实例变量和 get/set 方法。
主要活动:
package tj.apps.files;
import java.io.File;
import java.util.ArrayList;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.ImageView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
public class FilesList extends SherlockFragmentActivity implements ListFragment.listFragmentListener {
// Constructors
private ItemAdapter aa;
private ArrayList<Item> array;
private String extMountState = Environment.getExternalStorageState();
private String rootPath;
private ArrayList<Item> items;
private FragmentManager fm;
private FragmentTransaction ft;
private ListFragment listFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.files_list);
// Set up FragmentManager and FragmentTransaction
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
// Comments below is code that doesn't work, as it returns false always on my Galaxy Nexus
/*
// Checking whether or not external storage is mounted or not
// If it isn't mounted, then an ErrorFragment is shown, which is an
// ImageView saying media isn't mounted and to restart app once it is.
if (!(extMountState == (Environment.MEDIA_MOUNTED))) {
ft.add(R.id.container_fragment_listview, new ErrorFragment());
ft.commit();
// If it is mounted, the files are retrieved using getFileDirectory,
// the ListFragment is loaded and set with the ItemAdapter.
} else {
*/
File file = Environment.getExternalStorageDirectory();
rootPath = file.getPath();
listFragment = new ListFragment();
ft.add(R.id.container_fragment_listview, listFragment);
ft.commit();
listFragment.getFileDir(rootPath);
}
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.files_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_search:
return true;
case R.id.menu_edit_mode:
return true;
case R.id.menu_help:
return true;
case R.id.menu_about:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void addNewFragment(String path) {
ListFragment other = new ListFragment();
ft.replace(R.id.container_fragment_listview, other);
ft.addToBackStack(null);
ft.commit();
other.getFileDir(path);
}
}
列表片段:
package tj.apps.files;
import java.io.File;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockListFragment;
public class ListFragment extends SherlockListFragment {
// constructors
private ArrayList<Item> items;
private ItemAdapter adapter;
private listFragmentListener lfListener;
// Get reference to interface in Activity
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
try {
lfListener = (listFragmentListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException (activity.toString() + "must implement listFragmentListener");
}
}
// Inflate custom list at R.layout.fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.list_fragment, container, false);
}
// Method to create ListFragment from storage path
public void getFileDir(String path) {
// Get the File using the 'path' parameter, then gets the directory at
// that path, while also initializing the 'items' ArrayList
File f = new File(path);
File[] files = f.listFiles();
items = new ArrayList<Item>();
// Loops through File[], gets the File at the current position in the
// File[], gets name/extension/path and puts them to strings,
// Creates a new Item using those. Those are then added to the 'items'
// ArrayList
for (int i = 0; i < files.length; i++) {
File file = files[i];
String name = file.toString();
String filePath = file.getPath();
String extension;
// If it's a file, then grab the file's extensions (.jpg, .txt,
// ex.). If it's a folder, get the length of the directory.
if (file.isFile() == true) {
extension = name.substring(name.lastIndexOf('.') + 1);
} else {
extension = Integer.toString(files[i].listFiles().length)
+ "files";
}
items.add(new Item(name, extension, filePath));
}
// initializes ItemAdapter using 'items' and the custom row layout and
// grabbing the activity this fragment is attached to. Then sets it.
adapter = new ItemAdapter(getActivity(), R.layout.list_item, items);
setListAdapter(adapter);
}
// On list item click, we check if the file at the position is a folder or not. If it is, we call the listener.
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
File file = new File (items.get(position).getPath());
if (file.isDirectory()) {
lfListener.addNewFragment(items.get(position).getPath());
}
}
//Listener to communicate with Activity it is attached to. Meant to create a new Fragment.
public interface listFragmentListener {
public void addNewFragment(String path);
}
}
日志猫:
11-25 22:29:19.549: E/AndroidRuntime(12077): FATAL EXCEPTION: main
11-25 22:29:19.549: E/AndroidRuntime(12077): java.lang.RuntimeException: Unable to start activity ComponentInfo{tj.apps.files/tj.apps.files.FilesList}: java.lang.NullPointerException
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.os.Handler.dispatchMessage(Handler.java:99)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.os.Looper.loop(Looper.java:137)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread.main(ActivityThread.java:4745)
11-25 22:29:19.549: E/AndroidRuntime(12077): at java.lang.reflect.Method.invokeNative(Native Method)
11-25 22:29:19.549: E/AndroidRuntime(12077): at java.lang.reflect.Method.invoke(Method.java:511)
11-25 22:29:19.549: E/AndroidRuntime(12077): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
11-25 22:29:19.549: E/AndroidRuntime(12077): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
11-25 22:29:19.549: E/AndroidRuntime(12077): at dalvik.system.NativeStart.main(Native Method)
11-25 22:29:19.549: E/AndroidRuntime(12077): Caused by: java.lang.NullPointerException
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:153)
11-25 22:29:19.549: E/AndroidRuntime(12077): at tj.apps.files.ItemAdapter.<init>(ItemAdapter.java:21)
11-25 22:29:19.549: E/AndroidRuntime(12077): at tj.apps.files.ListFragment.getFileDir(ListFragment.java:73)
11-25 22:29:19.549: E/AndroidRuntime(12077): at tj.apps.files.FilesList.onCreate(FilesList.java:58)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.Activity.performCreate(Activity.java:5008)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-25 22:29:19.549: E/AndroidRuntime(12077): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-25 22:29:19.549: E/AndroidRuntime(12077): ... 11 more
我还在学习,我有点坚持解决这个问题。这是我正在尝试做的事情:
在 Main Activity 中,我尝试检查 SDCard 是否已安装,如果是,则会弹出 ErrorFragment。如果没有,我初始化一个 ListFragment,将它添加到 Main Activity 的 xml 中的容器中,然后在添加的 Fragment 上调用 ListFragment 方法之一。方法 getFileDir 基本上使用在 getFileDir 中用作参数的路径获取文件数组。然后,它使用 for 循环从数组中的每个文件中获取名称、扩展名和路径,创建一个新项目并将其添加到“项目”ArrayList 中。在循环之后,我使用自定义行布局(我测试为工作)初始化阵列适配器,使用'getActivity()'和'items'ArrayList 附加活动的上下文。然后我调用 setListAdapter。
编辑: Nandesh 知道了,它现在可以工作了。只是有另一个问题。我的列表项不可点击。这可能是我的 ItemAdapter 代码,如下所示:
package tj.apps.files;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ItemAdapter extends ArrayAdapter<Item> {
int resource;
Context context;
ArrayList<Item> items;
public ItemAdapter(Context context, int resource, ArrayList<Item> items) {
super(context, resource, items);
this.resource = resource;
this.context = context;
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(resource, parent, false);
holder = new ItemHolder();
convertView.setClickable(true);
convertView.setFocusable(true);
holder.text = (TextView) convertView.findViewById(R.id.item_text);
holder.subtext= (TextView) convertView.findViewById(R.id.item_subtext);
convertView.setTag(holder);
} else {
holder = (ItemHolder) convertView.getTag();
}
holder.text.setText(items.get(position).getName());
holder.subtext.setText(items.get(position).getType());
return convertView;
}
static class ItemHolder {
ImageView image;
TextView text;
TextView subtext;
}
}