2017-11-03 4 views
0

목록에서 프로그래밍 방식으로 생성 된 버튼의 스크롤 가능한 목록 (열을 보자)을 생성하는 활동은 sqlite 테이블을 읽은 결과이며 내 문제는 목록이 점점 커지고 있습니다 (버튼 수가 많아짐) 화면의 초기 그림이 느려지는 중입니다 (현재 50 개의 단추를 사용하여 3 초가 걸립니다). 그래서이 문제에 대한 해결책을 찾고 있습니다.프로그래밍 방식으로 생성 된 많은 버튼의 속도가 빨라짐

처음에는 스레드 (runnable, handler 또는 무엇이 가장 좋았는지)를 사용하여 생각했습니다. For 내부에 새 스레드를 만드는 것이 목록을 반복하지만 작동하지 않습니다. (또는 적어도 나는 할 수 없습니다.) 내 질문은 다음입니다 :

스크롤 버튼의 큰 세트를 만드는 가장 좋은 방법입니다 목록 <>에서 시작하므로 사용자가 화면에 액세스 할 때 그러한 지연을하지 않습니다.

페이지 매김은 옵션 일 수 있지만 다른 가능성을 먼저 알고 마지막 리소스로 남겨 두는 것이 좋습니다.

감사합니다. 아래 코드는 내 코드입니다.

public static void createButtons(LinearLayout llContainer, 
            List<TestType> TestTypes, List<Test> Tests, 
            int buttonFontSize) { 

     Context oContext = llContainer.getContext(); 
     String strTheme = TMAppearance.getThemeFromPreferences(oContext); 
     testMe = ((ApplicationConfiguration)oContext.getApplicationContext()); 
     int callerActivity = TestTypes!=null ? 2 : 1; 

     if (TestTypes!=null || Tests!=null) { 
      int lCols = strTheme.equals(testMe.theme_vivid) ? 1 : 2; 

      //int sourceElementIndex = 0; 
      int originListSize = calculateOriginalListSize(callerActivity, TestTypes, Tests); 
      int lRows = (int) Math.ceil((double)originListSize/lCols); 

      List<String> aStartColors = TMUtils_ThemeVivid.generateStartColorArray(lRows, oContext); 
      List<String> aEndColors = TMUtils_ThemeVivid.generateEndColorArray(lRows, oContext); 

      for (i = 0; i < lRows; i++) { 

       LinearLayout outerButtonLayout = generateOuterButtonLayout(oContext); 

       for (j = 0; j < lCols; j++) { 

        final Thread r = new Thread() { 
         public void run() { 
          LinearLayout innerButtonLayout = generateInnerButtonLayout(oContext); 
          outerButtonLayout.addView(innerButtonLayout, j); 

          if (sourceElementIndex<originListSize){ 
           final TMButton oButton = new TMButton(oContext); 

           if (callerActivity==1) { //testMenu 
            setTestMenuButtonSettings(oButton, sourceElementIndex, Tests); 
           } else { 
            if (callerActivity==2) { //testTypeMenu 
             setTestTypeMenuButtonSettings(oButton, sourceElementIndex, TestTypes); 
            } 
           } 

           if (strTheme.equals(testMe.theme_vivid)){ 
            oButton.fontSize = buttonFontSize; 
            oButton.gradientStartColor = aStartColors.get(i); 
            oButton.gradientEndColor = aEndColors.get(i); 
           }else{ 
            if (strTheme.equals(testMe.theme_purple)){ 
             oButton.gradientStartColor = testMe.btnStartColor_purple; 
             oButton.gradientEndColor = testMe.btnEndColor_purple; 
            } 
           } 

           configureButton(oButton, callerActivity); 

           oButton.setOnTouchListener(new OnTouchListener() { 
            @Override 
            public boolean onTouch(View v, MotionEvent event) { 

             Context oContext = v.getContext(); 
             TMButton oButton = (TMButton) v; 

             int callerActivity = Integer.valueOf(v.getTag().toString().split("@")[0]); 
             String sourceId = String.valueOf(v.getTag().toString().split("@")[1]); 

             if(event.getAction() == MotionEvent.ACTION_DOWN) { //pressed 
              setButtonPressed(oButton); 
              TMSound.playButtonSound(oContext); 
             } else if (event.getAction() == MotionEvent.ACTION_UP) { //released 
              setButtonReleased(oButton); 
              startTargetActivity(callerActivity, sourceId, oContext); 
             } 

             return true; 
            } 
           }); 
           TMAppearance.doButtonAnimation(oContext, oButton, i); 
           innerButtonLayout.addView(oButton); 
           sourceElementIndex++; 
          } 
         } 
        }; 
        r.run(); 
       } 
       llContainer.addView(outerButtonLayout); 
      } 
     } 
    } 
+0

에서보다 구현 쉽게 onClick 이벤트가'ListView' 또는 반대하는'RecycleView' 사용에 대한 뭔가가 있다는 것이다? 사용자 정의 레이아웃을 사용하면 유연성이 매우 높습니다. – Barns

+0

Barns52에 답장을 보내 주셔서 대단히 감사합니다. 물론 ListView에 반대하지는 않았습니다. 프로그래밍 방식으로 버튼이 생성되기 때문에 사실 ListView를 구현하는 방법을 조사하고 있습니다. 동적으로 생성 된 ListView를 문제없이 사용할 수 있다고 생각합니까? –

+0

ListView (nostalgia ?;-))를 좋아하지만 RecyclerView는 ListView와 비교하여 더 나은 성능을 제공합니다. 스크롤 할 때. – 0X0nosugar

답변

0

0X0nosugar 올바른 것입니다. A RecycleView은 더 나은 성능을 제공하지만 많은 초보자가이 기능을 구현하는 데 어려움을 겪고 있으며 50 개의 버튼 성능만으로는 문제가되지 않습니다. 그리고 저는 일반적으로 '최상의 사용 가능한 솔루션 사용'규칙을 따르기를 원하지만, ListView을 구현하는 방법을 배우는 것은 여전히 ​​적절하다고 생각합니다. 그래서 ...

사용자 정의 어댑터를 작성해야합니다 :

public class MyListData { 

    // Add more as you need 
    private long userId; 
    private String firstName; 

    public MyListData(){ 
    } 


    public void setFirstName(String name){ this.firstName = name; } 
    public void setUserId(long id){ this.userId = id; } 

    public String getFirstName(){ return this.firstName; } 
    public long getUserId(){ return this.userId; } 
} 

귀하의 사용자 정의 ListView 레이아웃이 같은 것을 볼 수 있었다 :

public class MyListDataAdapter extends ArrayAdapter<MyListData> { 

    private static final String TAG = "MyListDataAdapter"; 


    public MyListDataAdapter(Context context, ArrayList<MyListData> data) { 
     super(context, 0, data); 

    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent){ 

     final MyListData data = getItem(position); 

     if(convertView == null){ 
      convertView = LayoutInflater.from(getContext()).inflate(R.layout.edit_list_item, parent, false); 
     } 

     // Add a TextView if you need one 
     final TextView tvName = (TextView) convertView.findViewById(R.id.tvName); 
     Button btnEditTicketHolder = (Button) convertView.findViewById(R.id.btnEdit); 
     btnEditTicketHolder.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       long userId = data.getUserId(); 
       String fName = data.getFirstName(); 

       Intent intent = new Intent(getContext(), EditActivity.class); 
       intent.putExtra("userId", userId); 
       intent.putExtra("fName", fName); 
       getContext().startActivity(intent); 
      } 
     }); 


     String name = data.getFirstName(); 
     tvName.setText(name); 
     return convertView; 
    } 

} 

는 이제 데이터를 보유하기 위해 MyListData 클래스를 필요 :

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       xmlns:app="http://schemas.android.com/apk/res-auto" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
    > 

    <LinearLayout 
     android:orientation="vertical" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_centerVertical="true" 
     > 

     <TextView 
      android:id="@+id/tvName" 
      android:text="With Whom" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      /> 

    </LinearLayout> 

    <LinearLayout 
     android:orientation="vertical" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentRight="true" 
     android:layout_centerVertical="true" 
     > 

     <Button 
      android:id="@+id/btnEdit" 
      android:layout_width="wrap_content" 
      android:layout_height="40dp" 
      android:paddingRight="10dp" 
      android:paddingLeft="10dp" 
      android:text="Edit" 
      android:backgroundTint="@color/colorAccent" 
      android:focusable="false" 
      /> 

    </LinearLayout> 

</RelativeLayout> 

활동 내에서 (예 : onCreate() 방법) ListView에 대한 데이터를 채워야하는 경우. 이것은 ListView가 필요할 경우 일부 onClick 이벤트 핸들러를 설정 유지하는 활동에

ArrayList<MyListData> arrayListData = new ArrayList<MyListData>(); 
    MyListDataAdapter adapter = new MyListDataAdapter(this, arrayListData); 

    for (MyListData g : result) { 
     adapter.add(g); 
    } 
    mLstMy.setAdapter(adapter); 

또한 UI 스레드에서 수행 할 수 없습니다해야 (I 찾아 그 작은 장점 중 하나 ListView의가 RecycleView)

mMyLst = (ListView) findViewById(lstMy); 
mMyLst.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> parent, View view, int position, long l) { 
     MyListData data = (MyListData) parent.getItemAtPosition(position); 
     selectedName = data.getName(); 

     Intent intent = new Intent(ShowListDataActivity.this, MainActivity.class); 
     startActivity(intent); 
    } 
}); 

mMyLst.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
    @Override 
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { 

     MyListData data = (MyistData) adapterView.getItemAtPosition(i); 
     selectedName = data.getFirstName(); 

     selectedTicketPosition = i; 
     // removeValue is my own method for removing an entry from the 
     // list MyListData and then call adapter.notifyDataSetChanged(); 
     removeValue(i); 

     return true; 
    } 
}); 
+0

ListView에 대한 훌륭한 설명을 주신 Barns52에게 감사드립니다. 결국 RecyclerView를 구현할 수 있었지만 그 결과가 sqlite 쿼리에 지연이 있음을 발견하게되었습니다. 나는 그 쿼리를 최적화 할 수 있었고 결과적으로 화면 렌더링이 훨씬 빨라졌습니다. 모든 ListView 자습서를 작성했기 때문에 답변을 올바르게 설정합니다. –

관련 문제