0

ここ数日間、タブとフラグメントを使用して ActionBar を実装しました。

開発を進める前に、これまでのコードが最適かどうかを尋ねたいと思いました。または、失敗や「最善の解決策ではない」ことはありますか?

コードは次のとおりです。最初は MainActivity です。

public class MainActivity extends FragmentActivity 

public static int currentPos;

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

    ActionBar actionBar = getActionBar();

    Tab tabDashBoard = actionBar.newTab();
    tabDashBoard.setText("Dashboard");
    TabListener<DashBoardFragment> tabListenerDashBoard = new TabListener<DashBoardFragment>(this,"Dashboard", DashBoardFragment.class);
    tabDashBoard.setTabListener(tabListenerDashBoard);
    actionBar.addTab(tabDashBoard);

    Tab tabSuche = actionBar.newTab();
    tabSuche.setText("Suche");
    TabListener<SucheFragment> tabListenerSuche = new TabListener<SucheFragment>(this,"Suche",SucheFragment.class);
    tabSuche.setTabListener(tabListenerSuche);
    actionBar.addTab(tabSuche);

    Tab tabMap = actionBar.newTab();
    tabMap.setText("Map");
    TabListener<MapFragment> tabListenerMap = new TabListener<MapFragment>(this,"Map",MapFragment.class);
    tabMap.setTabListener(tabListenerMap);
    actionBar.addTab(tabMap);

    Tab tabProfil = actionBar.newTab();
    tabProfil.setText("Profil");
    TabListener<ProfilFragment> tabListenerProfil = new TabListener<ProfilFragment>(this,"Profil",ProfilFragment.class);
    tabProfil.setTabListener(tabListenerProfil);
    actionBar.addTab(tabProfil);

    Tab tabNachrichten = actionBar.newTab();
    tabNachrichten.setText("Nachrichten");
    TabListener<NachrichtenFragment> tabListenerNachrichten = new TabListener<NachrichtenFragment>(this,"Nachrichten",NachrichtenFragment.class);
    tabNachrichten.setTabListener(tabListenerNachrichten);
    actionBar.addTab(tabNachrichten);


    //actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);  
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);    
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(false);

     if( savedInstanceState != null ){
         actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tabState"));
     }
}

private class TabListener<T extends Fragment> implements ActionBar.TabListener
{
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(Activity activity,String tag,Class<T> clz) {
         mActivity = activity;
         mTag = tag;
         mClass = clz; 
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) 
    {
        currentPos = tab.getPosition();
        Fragment prevFragment;
        FragmentManager fm = mActivity.getFragmentManager();
        prevFragment = fm.findFragmentByTag(mTag); 
        if (prevFragment != null) { 
            mFragment = prevFragment; 
        } // previous Fragment management

        // Check if the fragment is already initialized
        if(mFragment == null){
            // If not, instantiate and add it to the activity:
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment,mTag);
        }else{
            // If it exists, simply attach it in order to show it:
            ft.attach(mFragment);
        }   
     }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) 
    {
        currentPos = tab.getPosition();
        if(mFragment != null){
             // Detach the fragment, because another one is being attached:
             ft.detach(mFragment);
        }else{
            // If not, instantiate and add it to the activity:
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment,mTag);
        }
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) 
    {
         // User selected the already selected tab. Usually do nothing. 
    }   
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("tabState", currentPos);
}   

そして今、例えばSucheFragmentクラス:

public class SucheFragment extends Fragment {

Activity currentActivity = getActivity();
ListView listView;
LayoutInflater inflaterT;

// ArrayList of type "Person". We are making not a list of string, sondern eine list of persons
ArrayList<Person> arrayOfWebData = new ArrayList<Person>();

class Person{
    public String person_id;
    public String name;
    public String birthday;
    public String favorite_color;
    public String profilbild;
}

// This is our new Adapter:
FancyAdapter aa = null;

// For each row we returned until we use the array to create our person obj
static ArrayList<String> resultRow;

@Override

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

        View view = inflater.inflate(R.layout.suche, container, false);
        inflaterT = inflater;
        listView = (ListView) view.findViewById(R.id.listView1);
        new getJson().execute("String");    
        return view;    
}

// JSON Response Example
private class getJson extends AsyncTask<String, String, JSONArray>
{
    @Override
    protected JSONArray doInBackground(String... params) 
    {
        String result = "";
        try{
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("xxxxxxxxxxx");
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            InputStream webs = entity.getContent();
            // Convert Response to String:
            try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(webs,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;

                while((line = reader.readLine()) != null){
                    sb.append(line+ "\n");  
                }
                webs.close();
                result = sb.toString(); 
            }catch(Exception e){
                e.printStackTrace();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        try{
            JSONArray jArray = new JSONArray(result);
            for(int i = 0;i < jArray.length();i++)
            {
                // Get our object, this is on persons data:
                JSONObject json_data = jArray.getJSONObject(i);
                // Create a new person:
                Person resultRow = new Person();
                // Set thats persons attributes:
                resultRow.person_id = json_data.getString("id");
                resultRow.name = json_data.getString("name");
                resultRow.favorite_color = json_data.getString("favorite_color");
                resultRow.birthday = json_data.getString("birthday");
                resultRow.profilbild = json_data.getString("profilbild");
                arrayOfWebData.add(resultRow);
            }   
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    protected void onPreExecute() {
         super.onPreExecute();

         Context context = getActivity();
         CharSequence text = "Lade Mitglieder";
         int duration = 5000;

         Toast toast = Toast.makeText(context, text, duration);
         toast.show();
    }
    @Override
    protected void onPostExecute(JSONArray result) {
        super.onPostExecute(result);
        populateListView(result);

    }       
}

public void populateListView(JSONArray result)
{
    final ListView myListView = (ListView) listView;
    // Initialize FancyAdapter object:
    aa = new FancyAdapter();
    myListView.setAdapter(aa);  

    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) 
        {
            // Get Person "behind" the clicked item
            Person p = (Person) myListView.getItemAtPosition(position);

            // Log the fields to check if we got the info we want
            Log.i("SomeTag", "Persons name: " + p.name);
            Log.i("SomeTag", "Persons id : " + p.person_id);

           Intent i = new Intent(getActivity(),ProfilAnsehenActivity.class);
           i.putExtra("mitglied_id", p.person_id);
           i.putExtra("mitglied_benutzername", p.name);
           i.putExtra("profilbild", p.profilbild);
           startActivity(i);
        }
    });
}

class FancyAdapter extends ArrayAdapter<Person>
{
    FancyAdapter(){
        super(getActivity(),android.R.layout.simple_list_item_1,arrayOfWebData);
        //imageLoader = new ImageLoader(MainActivity.this);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if(convertView == null){
            LayoutInflater inflater = inflaterT;
            convertView = inflater.inflate(R.layout.row3, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder); 
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        holder.populateFrom(arrayOfWebData.get(position));
        return convertView; 
    }
}

class ViewHolder
{
    public TextView name = null;
    public TextView birthday = null;
    public TextView favorite_color = null;
    public ImageView profilbild = null;
    //public ImageLoader imageLoader;
    ImageLoader imageLoader = new ImageLoader(getActivity());

    ViewHolder(View row){
        name = (TextView)row.findViewById(R.id.name);
        birthday = (TextView)row.findViewById(R.id.birthday);
        favorite_color = (TextView)row.findViewById(R.id.favorite_color);
        profilbild = (ImageView)row.findViewById(R.id.imageView1);  
    }
    // Notice we have to change our populateFrom() to take an argument of type "Person"
    void populateFrom(Person r){
        name.setText(r.name);
        birthday.setText(r.birthday);
        favorite_color.setText(r.favorite_color);
        imageLoader.DisplayImage(r.profilbild, profilbild); 
    }   
}   

上記の「SucheFragment」内からActivityを起動してもよろしいでしょうか?最後に、ProfilAnsehenActivity: (ListView アイテムをクリックすると呼び出されます):

public class ProfilAnsehenActivity extends Activity implements ActionBar.TabListener {


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


    ActionBar actionBar = getActionBar();

    /*Tab tabDashBoard = actionBar.newTab();
    tabDashBoard.setText("Profil");
    tabDashBoard.setTabListener(this);
    actionBar.addTab(tabDashBoard);

    Tab tabDashBoard2 = actionBar.newTab();
    tabDashBoard2.setText("Fotos");
    tabDashBoard2.setTabListener(this);
    actionBar.addTab(tabDashBoard2);

    Tab tabDashBoard3 = actionBar.newTab();
    tabDashBoard3.setText("Nachricht senden");
    tabDashBoard3.setTabListener(this);
    actionBar.addTab(tabDashBoard3);*/

    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);    
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(false);



    Intent intent = getIntent();
    String mitglied_benutzername = intent.getStringExtra("mitglied_benutzername");
    String mitglied_id = intent.getStringExtra("mitglied_id");
    String profilbild = intent.getStringExtra("profilbild");

    TextView benutzername = (TextView)findViewById(R.id.textViewBenutzername);
    benutzername.setText(mitglied_benutzername);

    TextView mitglied_idV = (TextView)findViewById(R.id.textViewMitgliedId);
    mitglied_idV.setText("Mitglied-ID:" +mitglied_id);

    ImageView imageV = (ImageView)findViewById(R.id.imageView2);

    ImageLoader imageLoader = new ImageLoader(ProfilAnsehenActivity.this);
    imageLoader.DisplayImage(profilbild, imageV);       
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        // This ID represents the Home or Up button. In the case of this
        // activity, the Up button is shown. Use NavUtils to allow users
        // to navigate up one level in the application structure. For
        // more details, see the Navigation pattern on Android Design:
        //
        // http://developer.android.com/design/patterns/navigation.html#up-vs-back
        //
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}

どう思いますか ?私からの「誤解」はありますか?ところで:

向きを縦から横に変更すると、getJson-Method が再度呼び出され、インターネットからの json-data が再度読み込まれます...「SucheFragment」が json-data を再度ダウンロードしないようにするにはどうすればよいですか? 向きを変える前と同じデータを表示したい…

こんにちは、ジュリアン

4

3 に答える 3

0

あなたは付け加えられます

android:configChanges="orientation" 

アクティビティのマニフェストで、json-data が再度ダウンロードされるのを防ぎます。

この行を追加することにより、onCreate() メソッドは方向が変更されたときに呼び出されなくなり、方向が変更される前と同じデータが表示されます。

ただし、UI の変更を処理する必要があります。

これがあなたを助けることを願っています..

于 2013-01-09T05:09:44.433 に答える
0

少なくとも、非静的内部クラスはデバイスのローテーションでメモリ ライクを引き起こすため、 Activityasのすべての内部クラスを作成する必要があります。static

AsyncTaskまた、ネットワークに使用するのは最善のアイデアではありません。 IntentService+SQLiteアプローチを使用することをお勧めします。たとえば、REST のベスト プラクティスに関する Google I/O のこのビデオを確認できます。

向きを変える前と同じデータを表示したい…

フラグメント内にフラグを保存し、new getJson().execute("String");1 回だけ呼び出すことができます。AsyncTaskただし、ネットワーク関連の場所として最適な場所ではないことを忘れないでください。

フラグ コード サンプル (フラグメント内):

....
private boolean isAlreadyRunned = fasle;

.... (onCreateView())
if (!isAlreadyRunned){
    new getJson().execute("String");
}

...(getJson)
 arrayOfWebData.add(resultRow);
 isAlreadyRunned = true;

そんな感じ)))

于 2013-01-09T05:19:10.753 に答える
0

フラグ「private boolean jsonDataLoaded = false;」を追加しました。

アプリが最初にデータをロードするときに、true に設定します。次に、onCreateView() で、フラグが false かどうかを確認します。false の場合は、geJson() にジャンプしないでください。

getJson() が呼び出されたら、jsonDataLoaded を TRUE に設定します。

expexted のように動作します: 1) jsonData を読み込み、フラグを TRUE に設定します 2) 他のタブに変更して、SucheFragment に戻った後、フラグは TRUE になり、データは読み込まれません:

BUT:データはロードされません(正しい動作)が 、ListViewは以前に受信したデータで満たされません。

ここで、SucheFragment のコード:

public class SucheFragment extends Fragment {

Activity currentActivity = getActivity();
ListView listView;
LayoutInflater inflaterT;

// ArrayList of type "Person". We are making not a list of string, sondern eine list of persons
ArrayList<Person> arrayOfWebData = new ArrayList<Person>();

class Person{
    public String person_id;
    public String name;
    public String birthday;
    public String favorite_color;
    public String profilbild;
}

// This is our new Adapter:
FancyAdapter aa = null;

// For each row we returned until we use the array to create our person obj
static ArrayList<String> resultRow;

// If true,- the JSON data has been loaded:
private boolean jsonDataLoaded = false;

@Override
// Create and return the view hierarchy associated with the fragment
// The System invokes this method when its time for the fragment to create its layout
// This method must return a View that is the ROOT of your fragments layout
// Parameter "container": Is the parent of the View (e.g LinearLayout etc)
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        // Parameter: 
        //      1) RESOURCE:        ID for an XML Layout Resource
        //      2) ROOT:            An object that provides a set of LayoutParams values for root of the returned hierarchy (if 3.Parameter is false)
        //      3) attachToRoot:    Whether the inflated hierarchy should be attached to the root parameter
        //                          If ROOT, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
        //                          Wenn FALSE,- prevents the inflater from automatically attaching the inflated view hierarchy to the parent container
        View view = inflater.inflate(R.layout.suche, container, false);
        inflaterT = inflater;
        listView = (ListView) view.findViewById(R.id.listView1);

        Log.i("TEST","LOADED "+jsonDataLoaded);

        if(!jsonDataLoaded){
            new getJson().execute("String");    
        }




        return view;    
}

// JSON Response Example
private class getJson extends AsyncTask<String, String, JSONArray>
{
    @Override
    protected JSONArray doInBackground(String... params) 
    {
        String result = "";
        try{
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("xxx");
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            InputStream webs = entity.getContent();
            // Convert Response to String:
            try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(webs,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;

                while((line = reader.readLine()) != null){
                    sb.append(line+ "\n");  
                }
                webs.close();
                result = sb.toString(); 
            }catch(Exception e){
                e.printStackTrace();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        try{
            JSONArray jArray = new JSONArray(result);
            for(int i = 0;i < jArray.length();i++)
            {
                // Get our object, this is on persons data:
                JSONObject json_data = jArray.getJSONObject(i);
                // Create a new person:
                Person resultRow = new Person();
                // Set thats persons attributes:
                resultRow.person_id = json_data.getString("id");
                resultRow.name = json_data.getString("name");
                resultRow.favorite_color = json_data.getString("favorite_color");
                resultRow.birthday = json_data.getString("birthday");
                resultRow.profilbild = json_data.getString("profilbild");
                arrayOfWebData.add(resultRow);

            }   
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    protected void onPreExecute() {
         super.onPreExecute();

         Context context = getActivity();
         CharSequence text = "Lade Mitglieder";
         int duration = 5000;

         Toast toast = Toast.makeText(context, text, duration);
         toast.show();
    }
    @Override
    protected void onPostExecute(JSONArray result) {
        super.onPostExecute(result);
        populateListView(result);
        jsonDataLoaded = true;

    }       
}

public void populateListView(JSONArray result)
{
    final ListView myListView = (ListView) listView;
    // Initialize FancyAdapter object:
    aa = new FancyAdapter();
    myListView.setAdapter(aa);  

    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) 
        {
            // Get Person "behind" the clicked item
            Person p = (Person) myListView.getItemAtPosition(position);

            // Log the fields to check if we got the info we want
            Log.i("SomeTag", "Persons name: " + p.name);
            Log.i("SomeTag", "Persons id : " + p.person_id);

           Intent i = new Intent(getActivity(),ProfilAnsehenActivity.class);
           i.putExtra("mitglied_id", p.person_id);
           i.putExtra("mitglied_benutzername", p.name);
           i.putExtra("profilbild", p.profilbild);
           startActivity(i);
        }
    });
}

class FancyAdapter extends ArrayAdapter<Person>
{
    FancyAdapter(){
        super(getActivity(),android.R.layout.simple_list_item_1,arrayOfWebData);
        //imageLoader = new ImageLoader(MainActivity.this);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if(convertView == null){
            LayoutInflater inflater = inflaterT;
            convertView = inflater.inflate(R.layout.row3, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder); 
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        holder.populateFrom(arrayOfWebData.get(position));
        return convertView; 
    }
}

class ViewHolder
{
    public TextView name = null;
    public TextView birthday = null;
    public TextView favorite_color = null;
    public ImageView profilbild = null;
    //public ImageLoader imageLoader;
    ImageLoader imageLoader = new ImageLoader(getActivity());

    ViewHolder(View row){
        name = (TextView)row.findViewById(R.id.name);
        birthday = (TextView)row.findViewById(R.id.birthday);
        favorite_color = (TextView)row.findViewById(R.id.favorite_color);
        profilbild = (ImageView)row.findViewById(R.id.imageView1);  
    }
    // Notice we have to change our populateFrom() to take an argument of type "Person"
    void populateFrom(Person r){
        name.setText(r.name);
        birthday.setText(r.birthday);
        favorite_color.setText(r.favorite_color);
        imageLoader.DisplayImage(r.profilbild, profilbild); 
    }   
}   
于 2013-01-10T10:58:05.553 に答える